Оптимизация цикла Python

В настоящее время я работаю с файлом с более чем 2 миллионами строк. Я разделил строки на списки элементов (например: [a,b,c,d]= 1 строка, слова разделены).

Я пытаюсь использовать следующий код для прохождения всех строк:

for a in aud:
    for esps in final:
        if a[0] in final[esps]:
            a[0] = esps

В первом цикле for я ссылаюсь на 2 миллиона + строк. Во втором цикле он проходит через словарь с ключами 2010, каждый ключ, возможно, не менее 50 соответствующих значений. Я хочу найти элемент a[0] в строках, которые равны значениям в словаре. Если они совпадают, я изменяю элемент a[0] в выбранной строке на значение ключа словаря.

Проблема заключается в том, что этот код требует много времени для запуска, и я не очень понимаю (ничего) об оптимизации и о том, как запустить это намного быстрее. Я бы поблагодарил много, если бы кто-нибудь мог сказать мне, как сделать что-то подобное быстрее.

Ответ 1

Когда у вас есть "большие" вещи, которые нужно выполнить, таким образом, ключ к быстрому ходу - "уменьшить алгоритмическую сложность", то есть избегать любых операций, зависящих от размера любого набора данных, если это возможно.

В примере, который вы дали, вы выполняете для каждой из ваших миллионов строк линейный поиск 50 x 2000 - это много! Проблема состоит в том, что если каждый из ваших final[esps] является списком, Python выполняет линейный поиск в этих 50 значениях - с оператором in.

Поскольку вы упоминаете, что читаете свои значения из файла, я должен предположить, что и [0], и элементы в строках final являются строками, но это также будет работать для чисел.

Первая, очень простая оптимизация состоит в том, чтобы просто изменить ваши словарные строки final из списков в set - с помощью set совпадение с оператором in изменилось с линейного на постоянное время ( от O (m) до O (1)). Таким образом, вы в основном сокращаете время поиска в 50 раз, прежде чем запускать код в своем примере:

for key in final:
   final[key] = set(final[key])

Но вы по-прежнему выполняете линейный поиск в каждом из ключей 2010 года final. Способ изменить это на постоянный поиск - создать обратный словарь, в котором каждое из 50 значений в строке final вместо этого указывает на ключ esp. Затем вы просто используете [0] в качестве ключа в этом перевернутом словаре - и вы заменяете линейный поиск в 100000 элементах (2000 x 50) для поиска в постоянное время в словаре;

Это легко сделать - просто измените свой код на:

rfinal = {}
for esp, values in final.items():
   for value in values:
       rfinal[value] = esp


for a in aud:
    if a[0] in rfinal:
       a[0] = rfinal[a[0]]
    else:
       # code for when there is no match for a[0]
       ...