it-swarm.com.ru

Python словарь против списка, который быстрее?

Я кодировал проблему Эйлера и столкнулся с вопросом, который вызвал мое любопытство. У меня есть два фрагмента кода. Один со списками, другой использует словари. 

используя списки :

n=100000
num=[]
suma=0
for i in range(n,1,-1):
    tmp=Tuple(set([n for n in factors(i)]))
    if len(tmp) != 2: continue
    if tmp not in num:
       num.append(tmp)
           suma+=i

используя словари :

n=100000
num={}
suma=0
for i in range(n,1,-1):
   tmp=Tuple(set([n for n in factors(i)]))
   if len(tmp) != 2: continue
   if tmp not in num:
      num[tmp]=i
      suma+=i

Я беспокоюсь только о производительности. Почему второй пример с использованием словарей работает невероятно быстро, быстрее, чем первый пример со списками. пример со словарями работает почти в тридцать раз быстрее!

Я проверил эти 2 кода, используя n = 1000000, и первый код выполняется за 1032 секунды, а второй - всего за 3,3 секунды , amazin '!

8
froycard

В Python средняя сложность поиска ключа в словаре по времени составляет O (1), поскольку они реализованы в виде хеш-таблиц. Временная сложность поиска в списке в среднем составляет O(n). В вашем коде это имеет значение в строке if tmp not in num:, так как в случае со списком Python необходимо выполнить поиск по всему списку, чтобы определить членство, тогда как в случае с dict это не так, за исключением абсолютно худшего случая.

Для более подробной информации, проверьте TimeComplexity .

10
Karin

Если речь идет о скорости, вы не должны создавать списки:

n = 100000
factors = ((frozenset(factors(i)), i) for i in range(2, n+1))
num = {k:v for k,v in factors if len(k)==2}
suma = sum(num.values())
2
Daniel

В списке код if tmp not in num: - это O (n)в то время как это O(lgn) в dict,.

Правка : диктат основан на хешировании, поэтому он намного быстрее, чем поиск по списку лайнеров . Спасибо @ user2357112 за указание этого.

0
citaret

Я почти уверен, что "волшебный соус", использующий словарь, заключается в том, что словарь состоит из пар ключ -> значение.

в списке вы имеете дело с массивами, что означает, что цикл for должен начинаться с индекса 0 внутри вашего списка, чтобы проходить по каждой записи.

словарь просто должен найти соответствующую пару ключ-> значение в первом цикле и вернуть ее, отсюда скорость ...

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

0
lopezdp