Наиболее эффективный итерация большого списка словарей в Python - PullRequest
0 голосов
/ 15 сентября 2018

Я видел некоторые ответы на похожие вопросы, но я не уверен, что они были лучшим способом решения моей проблемы.

У меня обрабатывается очень большая таблица (100 000+ строк из 20+ столбцов)как список словарей.Мне нужно сделать частичную дедупликацию этого списка, используя сравнение.Ниже я упростил пример того, что я делаю сейчас.

table = [
    { "serial": "111", "time": 1000, "name": jon },
    { "serial": "222", "time": 0900, "name": sal },
    { "serial": "333", "time": 1100, "name": tim },
    { "serial": "444", "time": 1300, "name": ron },
    { "serial": "111", "time": 1300, "name": pam }
    ]

for row in table:
    for row2 in table:
        if row != row2:
            if row['serial'] == row2['serial']:
                if row['time'] > row2['time']:
                    action

Этот метод работает (очевидно, упростил и просто написал «действие» для этой части), но у меня есть вопрос, есть ли болееэффективный метод, чтобы добраться до "строки", которую я хочу, без необходимости повторять всю таблицу.У меня нет способа обязательно предсказать, где в списке будут находиться совпадающие строки, но в этом случае они будут перечислены под одним и тем же «серийным номером».

Я относительно новичок в Python и эффективностиэто цель здесь.На данный момент с количеством повторяющихся строк это занимает много времени, и я уверен, что есть более эффективный способ сделать это, я просто не уверен, с чего начать.

Спасибо за любую помощь!

Ответы [ 4 ]

0 голосов
/ 16 сентября 2018

@ GiraffeMan91 Просто чтобы уточнить, что я имею в виду (напечатано прямо здесь, не копируйте и не вставляйте):

serials = collections.defaultdict(list) 
for d in table:
    serials[d.pop('serial')].append(d)

def process_serial(entry):
    serial, values = entry
    # remove duplicates, take action based on time
    # return serial, processed values

results = dict(
    multiprocess.Pool(10).imap(process_serial, serials.iteritems())
)
0 голосов
/ 15 сентября 2018

Возможно, это не самый эффективный способ, но вы можете получить список серийных номеров и отсортировать их. Давайте назовем этот список serialNumbersList. Серийные номера, которые появляются только один раз, мы знаем, что они не могут быть дубликатами, поэтому мы удаляем их из serialNumbersList. Затем вы можете использовать этот список, чтобы уменьшить количество строк для обработки. Опять же, я уверен, что есть лучшие решения, но это хорошая отправная точка.

0 голосов
/ 15 сентября 2018

Вы можете отсортировать таблицу с serial в качестве первичного ключа и time в качестве вторичного ключа в обратном порядке (так, чтобы последний из повторяющихся элементов имел приоритет), затем выполнить итерацию по отсортированному списку и принять меры только по первому указанию каждого отдельного serial:

from operator import itemgetter
table = [
    { "serial": "111", "time": "1000", "name": "jon" },
    { "serial": "222", "time": "0900", "name": "sal" },
    { "serial": "333", "time": "1100", "name": "tim" },
    { "serial": "444", "time": "1300", "name": "ron" },
    { "serial": "111", "time": "1300", "name": "pam" }
]
last_serial = ''
for d in sorted(table, key=itemgetter('serial', 'time'), reverse=True):
    if d['serial'] != last_serial:
        action(d)
    last_serial = d['serial']
0 голосов
/ 15 сентября 2018

Список словарей: всегда будет довольно медленным для такого большого количества данных. Вместо этого посмотрите, подходит ли Pandas для вашего случая использования - он уже оптимизирован для такого рода работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...