У меня есть список диктов, и я хотел бы удалить диктанты с одинаковыми парами ключ и значение.
Для этого списка: [{'a': 123}, {'b': 123}, {'a': 123}]
Я хотел бы это вернуть: [{'a': 123}, {'b': 123}]
Другой пример:
Для этого списка: [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}, {'a': 123, 'b': 1234}]
Я хотел бы это вернуть: [{'a': 123, 'b': 1234}, {'a': 3222, 'b': 1234}]
python
list
dictionary
Brenden
источник
источник
set()
Ответы:
Попробуй это:
Стратегия заключается в преобразовании списка словарей в список кортежей, в которых кортежи содержат элементы словаря. Так как кортежи можно хэшировать, вы можете удалить дубликаты, используя
set
(используя здесь понимание набора , более старая альтернатива Pythonset(tuple(d.items()) for d in l)
), и после этого заново создать словари из кортежей с помощьюdict
.где:
l
это оригинальный списокd
является одним из словарей в спискеt
является одним из кортежей, созданных из словаряРедактировать: Если вы хотите сохранить порядок, строка выше не будет работать, так
set
как не будет делать это. Однако, с помощью нескольких строк кода, вы также можете сделать это:Пример вывода:
Примечание: как указывает @alexis, может случиться так, что два словаря с одинаковыми ключами и значениями не приведут к одному и тому же кортежу. Это может произойти, если они пройдут через другую историю добавления / удаления ключей. Если это относится к вашей проблеме, то рассмотрите сортировку,
d.items()
как он предлагает.источник
d.items()
не гарантируется возврат элементов в определенном порядке. Вам следуетtuple(sorted(d.items()))
убедиться, что вы не получите разные кортежи для одних и тех же пар ключ-значение.json
модуля, как я это сделалЕще одна строка, основанная на списках:
Здесь, поскольку мы можем использовать
dict
сравнение, мы сохраняем только те элементы, которых нет в остальной части начального списка (это понятие доступно только через индексn
, отсюда и использованиеenumerate
).источник
if i not in d[n + 1:]
перебирает весь список диктовок (n
но только вдвое сокращает общее количество операций), и вы делаете эту проверку для каждого элемента в своем словаре, так что этот код имеет O (n ^ 2) временную сложностьДругие ответы не будут работать, если вы работаете с вложенными словарями, такими как десериализованные объекты JSON. Для этого случая вы можете использовать:
источник
Если вы можете использовать сторонний пакет, то вы можете использовать
iteration_utilities.unique_everseen
:Он сохраняет порядок исходного списка и может также обрабатывать не подлежащие изменению элементы, такие как словари, используя более медленный алгоритм (
O(n*m)
где вместоn
элементов находятся элементы в исходном списке иm
уникальные элементы в исходном спискеO(n)
). Если ключи и значения являются хэшируемыми, вы можете использоватьkey
аргумент этой функции для создания хэшируемых элементов для «теста уникальности» (чтобы он работалO(n)
).В случае словаря (который сравнивается независимо от порядка) вам необходимо сопоставить его с другой структурой данных, которая сравнивается следующим образом, например
frozenset
:Обратите внимание, что вы не должны использовать простой
tuple
подход (без сортировки), потому что равные словари не обязательно имеют одинаковый порядок (даже в Python 3.7, где порядок вставки - не абсолютный порядок - гарантирован):И даже сортировка кортежа может не работать, если ключи не сортируются:
эталонный тест
Я подумал, что было бы полезно увидеть сравнение этих подходов, поэтому я сделал небольшой тест. Графики сравнения времени и размера списка основаны на списке, не содержащем дубликатов (который был выбран произвольно, время выполнения существенно не изменится, если я добавлю несколько или много дубликатов). Это логарифмический сюжет, поэтому весь ассортимент покрыт.
Абсолютные времена:
Сроки относительно самого быстрого подхода:
Второй подход из четвертого здесь самый быстрый.
unique_everseen
Подход сkey
функцией находится на втором месте, однако это самый быстрый подход , который сохраняет заказ. Другие подходы от jcollado и thefourtheye почти такие же быстрые. Подход с использованиемunique_everseen
без ключа и решений из Эммануэля и Scorpil очень медленно для длинных списков и ведут себя гораздо хуже ,O(n*n)
аO(n)
. Подход stpk сjson
не является,O(n*n)
но он намного медленнее, чем аналогичныеO(n)
подходы.Код для воспроизведения тестов:
Для полноты здесь приведено время для списка, содержащего только дубликаты:
Времена не меняются значительно, за исключением
unique_everseen
безkey
функции, которая в этом случае является самым быстрым решением. Тем не менее, это просто лучший случай (поэтому не репрезентативный) для этой функции с непредсказуемыми значениями, потому что время ее выполнения зависит от количества уникальных значений в списке:O(n*m)
в данном случае это всего 1, и, следовательно, он выполняетсяO(n)
.Отказ от ответственности: я автор
iteration_utilities
.источник
Иногда петли старого стиля все еще полезны. Этот код немного длиннее, чем у jcollado, но очень легко читается:
источник
0
Вrange(0, len(a))
не нужно.Если вы хотите сохранить заказ, то вы можете сделать
Если порядок не имеет значения, то вы можете сделать
источник
dict_values
вывод вместо списка. Вы должны снова разыграть все это в списке.list(frozen.....)
Если вы используете Pandas в своем рабочем процессе, одним из вариантов является передача списка словарей непосредственно в
pd.DataFrame
конструктор. Затем используйтеdrop_duplicates
иto_dict
методы для получения требуемого результата.источник
Не универсальный ответ , но если ваш список отсортирован по некоторому ключу, например так:
тогда решение так же просто, как:
Результат:
Работает с вложенными словарями и (очевидно) сохраняет порядок.
источник
Вы можете использовать набор, но вам нужно превратить дикты в тип hashable.
Уникальный сейчас равен
Чтобы вернуть слова:
источник
d.iteritems()
не гарантируется - поэтому вы можете получить «дубликаты» вunique
.Вот быстрое однострочное решение с вдвойне понятным списком (основанное на решении @Emmanuel).
При этом используется один ключ (например,
a
) в каждом диктовке в качестве первичного ключа, а не проверка соответствия всего диктовки.Это не то, о чем просил OP, но это то, что привело меня в эту ветку, поэтому я решил опубликовать решение, с которым у меня получилось
источник
Не такой короткий, но легко читаемый:
Теперь список
list_of_data_uniq
будет иметь уникальные диктанты.источник