Предположим, у меня есть два словаря Python - dictA
и dictB
. Мне нужно выяснить, есть ли какие-либо ключи, которые присутствуют в, dictB
но не в dictA
. Какой самый быстрый способ сделать это?
Должен ли я преобразовать ключи словаря в набор, а затем пойти дальше?
Интересно узнать ваши мысли ...
Спасибо за ваши ответы.
Извиняюсь за неправильное изложение моего вопроса. Мой сценарий такой: у меня есть то, dictA
что может быть таким же, dictB
или может не хватать некоторых ключей по сравнению с dictB
другими, иначе значение некоторых ключей может отличаться, которое должно быть установлено на dictA
значение ключа.
Проблема в том, что словарь не имеет стандарта и может иметь значения, которые могут быть диктованными.
Сказать
dictA={'key1':a, 'key2':b, 'key3':{'key11':cc, 'key12':dd}, 'key4':{'key111':{....}}}
dictB={'key1':a, 'key2:':newb, 'key3':{'key11':cc, 'key12':newdd, 'key13':ee}.......
Таким образом, значение 'key2' должно быть сброшено на новое значение, а значение 'key13' должно быть добавлено в dict. Значение ключа не имеет фиксированного формата. Это может быть простая ценность или диктат или диктат диктата.
источник
def update(self, new_dict): self.__init__(new_dict, self.current_dict)
или иного, чтобы вы могли сделать скользящее сравнениеDictDiffer
класс является классом без состояний и может быть функцией. Значенияchanged
иunchanged
могут быть вычислены в одном цикле. Эти две функции могут возвращатьlist
вместо a,set
что, безусловно, дешевле. Для глубокого сравнения вы можете взглянуть на среду модульного тестирования: docs.python.org/2/library/unittest.html , просто следуйтеassertDictEqual
методу в исходном коде.set(dictb)
вероятно, лучше, чемset(dictb.keys())
.Если вы хотите рекурсивное различие, я написал пакет для Python: https://github.com/seperman/deepdiff
Монтаж
Установить из PyPi:
Пример использования
Импорт
Тот же объект возвращает пустой
Тип предмета изменился
Стоимость предмета изменилась
Товар добавлен и / или удален
Разница строк
Разница строк 2
Изменение типа
Разница в списке
Разница в списке 2:
Разница в списке, игнорирующая порядок или дубликаты: (с теми же словарями, что и выше)
Список, содержащий словарь:
Наборы:
Именованные кортежи:
Пользовательские объекты:
Добавлен атрибут объекта:
источник
ignore_order=True
. Вы можете найти документы по адресу deepdiff.readthedocs.io/en/latest/diff.htmlне уверен, что это "быстро" или нет, но обычно это можно сделать
источник
dicta
иdictb
так как он хочет знать, этих ключейdictb
нетdicta
.for key in dicta.keys():
=>for key in dicta:
Как писал Алекс Мартелли, если вы просто хотите проверить, не находится ли какой-либо ключ в B, не в A,
any(True for k in dictB if k not in dictA)
был бы путь.Чтобы найти отсутствующие ключи:
Таким образом, эти два решения практически одинаковы.
источник
any(k not in dictA for k in dictB)
Если вы действительно имеете в виду именно то, что говорите (то, что вам нужно только выяснить, ЕСЛИ «есть какие-то ключи» в B, а не в A, а НЕ КОГДА ОДНА из них, если таковые имеются), самый быстрый способ должен быть:
Если вам действительно нужно выяснить, КАКИЕ КЛЮЧИ, если они есть, находятся в B, а не в A, и не просто «ЕСЛИ» есть такие ключи, тогда существующие ответы вполне уместны (но я предлагаю большую точность в будущих вопросах, если это так. действительно, что вы имеете в виду ;-).
источник
Используйте
set()
:источник
set(d)
уже возвращает только ключи, так что вы можете сделатьset(da).intersection(db)
Главный ответ от hughdbrown предлагает использовать разность множеств, что, безусловно, является лучшим подходом:
Проблема этого кода в том, что он создает два списка только для создания двух наборов, поэтому он тратит 4N времени и 2N пространства. Это также немного сложнее, чем нужно.
Обычно это не имеет большого значения, но если это так:
collections.abc.Mapping
имеет a,KeysView
которое действует как aSet
.Python 2
В Python 2
keys()
возвращает список ключей, а не aKeysView
. Таким образом, вы должны попроситьviewkeys()
напрямую.Мы надеемся,
six
что для кода с двумя версиями 2.7 / 3.x вы используете или что-то подобное, поэтому вы можете использоватьsix.viewkeys(dictb)
:В 2.4-2.6 нету
KeysView
. Но вы можете, по крайней мере, сократить стоимость с 4N до N, построив свой левый набор непосредственно из итератора, вместо того, чтобы сначала создавать список:Предметы
Таким образом, вам действительно не нужно сравнивать ключи, но предметы. An
ItemsView
является толькоSet
если значения являются хэшируемыми, как строки. Если они есть, это легко:Рекурсивный дифференциал
Хотя вопрос напрямую не задает рекурсивный diff, некоторые из примеров значений являются dicts, и кажется, что ожидаемый результат действительно рекурсивно их дифференцирует. Здесь уже есть несколько ответов, показывающих, как это сделать.
источник
Есть еще один вопрос в stackoverflow об этом аргументе, и я должен признать, что есть простое объясненное решение: библиотека datadiff python помогает распечатать разницу между двумя словарями.
источник
Вот способ, который будет работать, учитывает ключи, которые оценивают
False
, и все еще использует выражение генератора, чтобы выпасть рано, если это возможно. Это не очень красиво, хотя.РЕДАКТИРОВАТЬ:
THC4k опубликовал ответ на мой комментарий к другому ответу. Вот лучший способ сделать это:
Не уверен, как это никогда не приходило мне в голову ...
источник
any(k for k in dictB if k not in dictA)
что это не одно и то же (для фальшивых ключей). Проверьте историю редактирования / метки времени.Это старый вопрос, и он требует немного меньше, чем мне было нужно, поэтому этот ответ на самом деле решает больше, чем этот вопрос. Ответы на этот вопрос помогли мне решить следующее:
Все это в сочетании с JSON обеспечивает довольно мощную поддержку конфигурации хранилища.
Решение ( также на github ):
источник
как насчет стандарта (сравните FULL Object)
PyDev-> Новый модуль PyDev-> Модуль: unittest
источник
Если на Python ≥ 2.7:
источник
Вот решение для глубокого сравнения двух словарей ключей:
источник
Вот решение, которое может сравнить более двух диктов:
пример использования:
источник
Мой рецепт симметричной разницы между двумя словарями:
И результат:
источник
Как уже упоминалось в других ответах, unittest выдает неплохой результат для сравнения dicts, но в этом примере нам не нужно сначала создавать целый тест.
Отбирая источник юнит-теста, похоже, что вы можете получить справедливое решение с помощью всего этого:
так
Результаты в:
Куда:
Как и в unittest, единственное предостережение заключается в том, что окончательное отображение можно считать diff из-за запятой / скобки.
источник
У @Maxx отличный ответ, используйте
unittest
инструменты, предоставляемые Python:Затем в любом месте вашего кода вы можете позвонить:
Результирующий вывод выглядит как вывод из «
diff
красивой печати» словарей с+
или-
добавляя каждую строку, которая отличается.источник
Не уверен, что это все еще актуально, но я столкнулся с этой проблемой, в моей ситуации мне просто нужно было вернуть словарь изменений для всех вложенных словарей и т. Д. И т. Д. Не удалось найти хорошее решение, но я в итоге написал простую функцию сделать это . Надеюсь это поможет,
источник
Если вам нужно встроенное решение для полного сравнения с произвольными структурами dict, ответ @ Maxx - хорошее начало.
источник
Основываясь на ответе ghostdog74,
будет печатать различное значение dicta
источник
Попробуйте это, чтобы найти де пересечение, ключи, которые есть в обоих словарях, если вы хотите, чтобы ключи не были найдены во втором словаре, просто используйте not in ...
источник