Подтвердить что ты не робот

Python - пересечение между списком и ключами словаря

У меня есть список, который выглядит так:

l1 = ['200:200', '90:728']

У меня есть словарь, который выглядит так:

d1 = {'200:200':{'foo':'bar'},'300:300':{'foo':'bar'}}

Мне нужно отфильтровать дикториал, где только ключи находятся в l1. Диктофон должен выглядеть так:

result = {'200:200':{'foo':'bar'}}

В сущности, пересечение списка и ключей dict при возврате подраздела dict.

Как мне сделать это эффективно, когда время является проблемой для больших наборов?

Спасибо

4b9b3361

Ответ 1

Вы можете использовать следующий код:

keys = set(l1).intersection(set(d1.keys()))
result = {k:d1[k] for k in keys}

EDIT:. Как говорят комментаторы, вы можете заменить первую строку на Python 2.x:

keys = set(l1).intersection(d1)

И в Python 3.x:

keys = d1.keys() & l1

Ответ 2

В 3.x это может быть просто:

>>> {k: d1[k] for k in (d1.keys() & l1)}
{'200:200': {'foo': 'bar'}}

В разделе 2.7 вы можете использовать dict.viewkeys() для воссоздания этой функции:

>>> {k: d1[k] for k in (d1.viewkeys() & l1)}
{'200:200': {'foo': 'bar'}}

В более старых версиях 2.x это несколько более подробный:

>>> {k: d1[k] for k in (set(d1).intersection(l1))}
{'200:200': {'foo': 'bar'}}

Ответ 3

Не уверен в производительности каждого решения, но я бы сделал:

{k: v for k, v in d1.items() if k in l1}

Ответ 4

Вы можете использовать понимание списка в конструкторе dict:

result = dict([(k,d1[k]) for k in l1 if k in d1])

Если вы беспокоитесь об удалении повторяющихся ключей, сначала сделайте l1 в наборе:

result = dict([(k,d1[k]) for k in set(l1) if k in d1])

Ответ 5

Определите эффективность. В любом случае, что бы я сделал. Если бы это было слишком медленно, я бы, вероятно, переместил его в Cython.

s1 = set(l1)
s2 = set(d1.keys())
s3 = s1 & s2
# now you can access d1 using only keys in s3, or construct a new dict if you like
d2 = dict([(k,d1[k]) for k in s3])

Ответ 6

Если распределение памяти и освобождение делают этот процесс слишком длинным, itertools на помощь.

import itertools
result = {dict_key:d1[dict_key] for dict_key in itertools.ifilter(lambda list_item: list_item in d1, l1) }

Это лишний раз выделяет память для всей новой коллекции, а l1 легко может быть итератором вместо списка.