У меня есть (потенциально довольно большой) словарь и список "возможных" ключей. Я хочу быстро найти, какой из ключей имеет соответствующие значения в словаре. Я нашел много обсуждений значений словаря здесь и здесь, но не обсуждается скорость или несколько записей.
Я придумал четыре способа, и для трех, которые работают лучше всего, я сравниваю их скорость с разными размерами выборки ниже - есть ли лучшие методы? Если люди могут предложить разумных соперников, я также подвергнув их анализу.
Примеры списков и словарей создаются следующим образом:
import cProfile
from random import randint
length = 100000
listOfRandomInts = [randint(0,length*length/10-1) for x in range(length)]
dictionaryOfRandomInts = {randint(0,length*length/10-1): "It here" for x in range(length)}
Метод 1: ключевое слово 'in'
:
def way1(theList,theDict):
resultsList = []
for listItem in theList:
if listItem in theDict:
resultsList.append(theDict[listItem])
return resultsList
cProfile.run('way1(listOfRandomInts,dictionaryOfRandomInts)')
32 вызова функций за 0,018 секунды
Метод 2: обработка ошибок:
def way2(theList,theDict):
resultsList = []
for listItem in theList:
try:
resultsList.append(theDict[listItem])
except:
;
return resultsList
cProfile.run('way2(listOfRandomInts,dictionaryOfRandomInts)')
32 вызова функций за 0.087 секунд
Метод 3: установить пересечение:
def way3(theList,theDict):
return list(set(theList).intersection(set(theDict.keys())))
cProfile.run('way3(listOfRandomInts,dictionaryOfRandomInts)')
26 вызовов функций за 0.046 секунд
Способ 4. Наивное использование dict.keys()
:
Это предостерегающая история - это была моя первая попытка и BY FAR самая медленная!
def way4(theList,theDict):
resultsList = []
keys = theDict.keys()
for listItem in theList:
if listItem in keys:
resultsList.append(theDict[listItem])
return resultsList
cProfile.run('way4(listOfRandomInts,dictionaryOfRandomInts)')
12 функций в 248.552 секунд
EDIT: Приведение предложений, приведенных в ответах, в те же рамки, которые я использовал для согласованности. Многие отметили, что в Python 3.x может быть достигнуто большее повышение производительности, в частности, методы, основанные на понимании списков. Большое спасибо за помощь!
Метод 5: лучший способ выполнения пересечения (спасибо jonrsharpe):
def way5(theList, theDict):
return = list(set(theList).intersection(theDict))
25 вызовов функций за 0.037 секунд
Метод 6: понимание списка (спасибо jonrsharpe):
def way6(theList, theDict):
return [item for item in theList if item in theDict]
24 вызова функций за 0,020 секунды
Метод 7: Использование ключевого слова &
(спасибо jonrsharpe):
def way7(theList, theDict):
return list(theDict.viewkeys() & theList)
25 функций в 0.026 секунд
Для методов 1-3 и 5-7 я приурочил их, как указано выше, со списком/словарями длиной 1000, 10000, 100000, 1000000, 10000000 и 100000000 и отображает график времени логарифмического журнала. По всей длине метод пересечения и in-statement работает лучше. Градиенты всего около 1 (возможно, немного выше), что указывает на O (n) или, возможно, немного суперлинейное масштабирование.