Удаление дубликатов объектов JSON из списка в python
у меня есть список dict, где определенное значение повторяется несколько раз, и я хотел бы удалить дубликаты значений.
мой список:
te = [
{
"Name": "Bala",
"phone": "None"
},
{
"Name": "Bala",
"phone": "None"
},
{
"Name": "Bala",
"phone": "None"
},
{
"Name": "Bala",
"phone": "None"
}
]
функция для удаления повторяющихся значений:
def removeduplicate(it):
seen = set()
for x in it:
if x not in seen:
yield x
seen.add(x)
когда я вызываю эту функцию, я получаю generator object
.
<generator object removeduplicate at 0x0170B6E8>
когда я пытаюсь перебрать генератор я вам TypeError: unhashable type: 'dict'
есть ли способ удалить повторяющиеся значения или выполнить итерацию по генератору
3 ответов
вы можете легко удалить дубликаты ключей по пониманию словаря, так как словарь не позволяет дублировать ключи, как показано ниже -
te = [
{
"Name": "Bala",
"phone": "None"
},
{
"Name": "Bala",
"phone": "None"
},
{
"Name": "Bala",
"phone": "None"
},
{
"Name": "Bala",
"phone": "None"
},
{
"Name": "Bala1",
"phone": "None"
}
]
unique = { each['Name'] : each for each in te }.values()
print unique
выход-
[{'phone': 'None', 'Name': 'Bala1'}, {'phone': 'None', 'Name': 'Bala'}]
потому что вы не можете добавить dict
to set
. От этот вопрос:
вы пытаетесь использовать
dict
как ключ к другойdict
илиset
. Что не работает, потому что ключи должны быть hashable.как правило, являются hashable только неизменяемые объекты (строки, целые числа, поплавки, frozensets, кортежи immutables) (хотя исключения возможны).
>>> foo = dict()
>>> bar = set()
>>> bar.add(foo)
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>>
вместо этого, вы уже используя if x not in seen
, поэтому просто используйте список:
>>> te = [
... {
... "Name": "Bala",
... "phone": "None"
... },
... {
... "Name": "Bala",
... "phone": "None"
... },
... {
... "Name": "Bala",
... "phone": "None"
... },
... {
... "Name": "Bala",
... "phone": "None"
... }
... ]
>>> def removeduplicate(it):
... seen = []
... for x in it:
... if x not in seen:
... yield x
... seen.append(x)
>>> removeduplicate(te)
<generator object removeduplicate at 0x7f3578c71ca8>
>>> list(removeduplicate(te))
[{'phone': 'None', 'Name': 'Bala'}]
>>>
вы все еще можете использовать set
для обнаружения дубликатов вам просто нужно преобразовать словарь в нечто хэшируемое, такое как tuple
. Ваши словари могут быть преобразованы в кортежи с помощью tuple(d.items())
здесь d
словарь. Применяя это к вашей функции генератора:
def removeduplicate(it):
seen = set()
for x in it:
t = tuple(x.items())
if t not in seen:
yield x
seen.add(t)
>>> for d in removeduplicate(te):
... print(d)
{'phone': 'None', 'Name': 'Bala'}
>>> te.append({'Name': 'Bala', 'phone': '1234567890'})
>>> te.append({'Name': 'Someone', 'phone': '1234567890'})
>>> for d in removeduplicate(te):
... print(d)
{'phone': 'None', 'Name': 'Bala'}
{'phone': '1234567890', 'Name': 'Bala'}
{'phone': '1234567890', 'Name': 'Someone'}
это обеспечивает более быстрый поиск (avg. O (1)) чем "видел" list
(O (n)). Стоит ли дополнительно вычислять преобразование каждого Дикта в кортеж, зависит от количества словарей что у вас есть и сколько дубликатов. Если есть много дубликатов, "видел" list
будет расти довольно большой, и тестирование того, был ли уже замечен dict, может стать дорогостоящей операцией. Это может оправдать преобразование кортежа - вам придется протестировать / профилировать его.