2012-06-22 2 views
12

У меня есть список, который выглядит следующим образом:Python - пересечение между списком и ключами словаря

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

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

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

Мне нужно, чтобы получить отфильтруйте дикториал, где только ключи находятся в l1. ДИКТ должен выглядеть следующим образом:

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

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

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

Благодаря

ответ

23

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

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 
+0

Обратите внимание, что в 3.x вид словаря установлен как-то, поэтому вам не нужно обертывать его в 'set()'. Фактически, в 3.x вся верхняя строка может быть 'keys = d1.keys() & l1'. –

+1

@Lattyware вам не нужно вводить его в набор в 2.x либо – jamylak

+4

Даже не нужны клавиши(), 'set (l1) .intersection (d1)' – georg

0

Вы можете использовать список понимание в конструкторе 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]) 
+0

Ключ не может быть в 'd1'. Это не сработает. –

+0

Также обратите внимание, что вы можете выполнять выражения генератора dict, как в моем решении. Итак, '{k: v для k, v в arr}'. Это даже имеет дело с дубликатами. – JPvdMerwe

+0

@JPvdMerwe Это понимание dict, а не выражение генератора dict - генераторные выражения ленивы, понимание dict не является. –

4

В 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.х, это чуть более многословен:

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

Я проверил документы. Похоже, что 'viewkeys()' доступно в 2.7, а не только 2.7.3. Он появляется в моей копии Python 2.7.1 – JPvdMerwe

+0

@JPvdMerwe Полезно знать, обновляется. –

3

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

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

Это будет работать, даже если член l1 не является ключом в d1, который многие другие не смогут выполнить. –

0

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

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]) 
0

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

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

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

Смежные вопросы