Удаление повторяющихся словарей в списке dicts на основе уникальности значения для данного ключа - PullRequest
1 голос
/ 29 мая 2020

У меня есть словарь:

dicts = [
{'id': 'item1', 'type': 'foo', 'metaId': 'metaId1'},
{'id': 'item2', 'type': 'foo', 'metaId': 'metaId2'},
{'id': 'item3', 'type': 'foo3', 'metaId': 'metaId3'},
{'id': 'item4', 'type': 'foo2', 'metaId': 'metaId2'},
{'id': 'item5', 'type': 'foo3', 'metaId': 'metaId3'},
{'id': 'item6', 'type': 'foo2', 'metaId': 'metaId2'},
{'id': 'item7', 'type': 'foo3', 'metaId': 'metaId3'},
{'id': 'item8', 'type': 'foo2', 'metaId': 'metaId2'},
{'id': 'item9', 'type': 'foo3', 'metaId': 'metaId3'}]

Я хочу l oop просмотреть список и создать новый список, содержащий словари с уникальными значениями для ключа 'type'. Мне все равно, какие словари останутся, первый экземпляр с этим ключом: значение остается, все остальное опущено. Итак, в конце я хотел бы увидеть:

expected = [
{'id': 'item1', 'type': 'foo', 'metaId': 'metaId1'},
{'id': 'item3', 'type': 'foo3', 'metaId': 'metaId3'},
{'id': 'item4', 'type': 'foo2', 'metaId': 'metaId2'}
]

Вот то, что я пробовал, определенно не то, что мне нужно, поскольку он возвращает пустой список. Я думаю, что мне трудно проверить значение в новом подсписке словарей, чтобы исключить его

keys_to_keep = set()
expected = []
for d in dicts:
    for key, value in d.items():
        if value not in expected:
            keys_to_keep.add(key)
remove_keys = set(d) - keys_to_keep

for d in dicts:
    for k in remove_keys:
        del d[k]
dicts = expected
print(dicts)

Ответы [ 3 ]

2 голосов
/ 29 мая 2020

Причина, по которой вы всегда получаете пустой список, заключается в том, что вы просто делаете:

dicts = expected

А expected - это просто пустой список, с которым вы никогда ничего не делали ... не знаю, зачем вам думаю, что expected когда-нибудь изменится.

Но вы слишком усложняете вещи. Просто сохраните набор уникальных значений и создайте новый список dicts.

seen = set()
result = []
for d in dicts:
    if d['type'] not in seen:
        result.append(d)
        seen.add(d['type'])

Этот подход сохраняет первый словарь, встречающийся с этим уникальным 'type'.

Если, например, вы хотите, чтобы встречались последние , вы можете сделать что-то вроде итерации по dicts в порядке уважения, поэтому

for d in reversed(dicts):
    ...
2 голосов
/ 29 мая 2020

Вы можете создать временный словарь для хранения первого словаря при первом обнаружении определенного типа, а затем использовать значения, которые попадают в него, для создания обновленного списка с одной дополнительной строкой кода.

dicts = [{'id': 'item1', 'type': 'foo', 'metaId': 'metaId1'},
         {'id': 'item2', 'type': 'foo', 'metaId': 'metaId2'},
         {'id': 'item3', 'type': 'foo3', 'metaId': 'metaId3'},
         {'id': 'item4', 'type': 'foo2', 'metaId': 'metaId2'},
         {'id': 'item5', 'type': 'foo3', 'metaId': 'metaId3'},
         {'id': 'item6', 'type': 'foo2', 'metaId': 'metaId2'},
         {'id': 'item7', 'type': 'foo3', 'metaId': 'metaId3'},
         {'id': 'item8', 'type': 'foo2', 'metaId': 'metaId2'},
         {'id': 'item9', 'type': 'foo3', 'metaId': 'metaId3'}]

temp = {}
for d in dicts:
    if d['type'] not in temp:
        temp[d['type']] = d

dicts = list(temp.values())  # Update list.

for d in dicts:
    print(d)
1 голос
/ 29 мая 2020

Сохраните видимые типы и добавьте отсутствующие в результирующий срез, а также отметьте их как видимые. Функция, которая делает это:

def transform(dicts):
  seen, result = set(), []
  for d in dicts:
    my_key = d['type']
    if my_key not in seen:
      result.append(d)
      seen.add(my_key)
  return result
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...