2012-04-22 2 views
6

Мне нужно было сравнить 2 словаря, чтобы найти набор ключей в одном словаре, который не был в другом.Краткий способ найти «ключевую» разницу между 2 словарями?

Я знаю, что Python набор объекты поддерживают:

set3=set1-set2 

, но я не могу сделать:

dict3=dict1-dict2 

или:

missingKeys=dict1.keys()-dict2.keys() 

(я был немного удивлен, по последней точке, потому что в Java ключи являются объектами Set.) Одно из решений:

missingKeys=set(dict1.keys())-set(dict2.keys()) 

есть ли лучший или более сжатый способ сделать это?

+0

Я думаю, что последняя строка достаточно кратким сам, но ... Я думаю, более интересный вопрос «Как удалить все z из Y из X?» где X и Y - списки. Это было бы полезно, если дублирующие z существуют в X, которые появляются в Y, например, должны быть оставлены в покое. –

+0

@pst: Ну, это немного странно для создания заданных объектов, просто чтобы использовать функцию разности() ... –

+0

С другой стороны, поскольку это * * набор, он может использовать лучшее O ... для различий в списках с помощью понимания легко, но немного более многословно. Тем не менее, такая же производительность, если «проверенный» список преобразуется в 'set'. –

ответ

3

Может

[x for x in dict1.keys() if x not in dict2.keys()] 
+2

Я думаю, что это может быть даже немного более кратким: '[x for x in dict1.keys(), если x не в dict2]', поскольку 'x in dict.keys()' совпадает с 'x in dict' – mgilson

+0

@mgilson: до тех пор, пока вы указали, что 'x in dict' совпадает с' x в dict.keys() ', тогда полное сокращение -' [x для x в dict1, если x не в dict2] '. –

+1

@SamGoldberg Вы правы.Причина, по которой я не думал об этом, состоит в том, что 'for x in dict' вызывает метод' __iter__' на dict, тогда как 'if x in dict' вызывает метод' __contains__'. Таким образом, в этом случае 'in' выполняет две разные вещи - они просто имеют одинаковый результат. Во всяком случае: '[x for x in dict1 if x not in dict2]' является наиболее кратким, как вы указали. – mgilson

15

Python 2.7:

>>> d = {1:2, 2:3, 3:4} 
>>> d2 = {2:20, 3:30} 
>>> set(d)-set(d2) 
set([1]) 

Python 3.2:

>>> d = {1:2, 2:3, 3:4} 
>>> d2 = {2:20, 3:30} 
>>> d.keys()-d2.keys() 
{1} 
+0

+1 О, подлый Python 3.x! –

+0

Итак, вы говорите, что метод python 3.2 dict.keys() возвращает набор (например, Java)? Любая причина, почему более ранняя версия этого не делала? –

+2

@SamGoldberg: нет, он фактически возвращает объект dict_keys, а не набор, но он имеет множество операций, подобных множеству. См., Например, [этот вопрос] (http://stackoverflow.com/questions/7296716/what-is-dict-keys-dict-items-and-dict-values). – DSM

4

Для портативных способ сделать это, я предложил бы использовать dict.viewkeys в Python 2.7 - это является backport из Python 3.x dict.keys и автоматически преобразуется на 2to3.

Пример:

>>> left = {1: 2, 2: 3, 3: 4} 
>>> right = {2: 20, 3:30} 
>>> left.viewkeys() - right.viewkeys() 
set([1]) 
1

Это должно работать в Python 2.7 и 3.x:

>>> keys = getattr(dict, 'viewkeys', dict.keys) 
>>> left = {1: 2, 2: 3, 3: 4} 
>>> right = {2: 20, 3:30} 
>>> list(keys(left) - keys(right)) 
[1]