набор словарей в списке словарей

пытаясь найти набор словарей в списке.

Скажем, у меня есть следующий список словарей:

rm_dict = [{'name':'rick','subject':'adventure time mortttty buugh','body':['wubba lubba dub dubbb motha f*&^%!', 'morty get over here!']},
 {'name':'rick','subject':'adventure time mortttty buugh','body':['wubba lubba dub dubbb motha f*&^%!', 'morty get over here!']},
 {'name':'morty','subject':'re:adventure time mortttty buugh','body':['youre drunk rick!', 'I'm going to get mom', 'you always do this']}]

пробую только set, получаю ошибку.

set(rm_dict)

Я беру тело сообщения/электронной почты, потому что это то, что я буду использовать для определения уникальности, и создаю список тела всех писем, а затем я создам генератор для set(tuple()) и т. д.

list_of_body = [x['body'] for x in rm_dict]
>>[['wubba lubba dub dubbb motha f*&^%!'],
  ['wubba lubba dub dubbb motha f*&^%!'],
  ['youre drunk rick!']]

[list(item) for item in set(tuple(row) for row in list_of_body)]
>>[['wubba lubba dub dubbb motha f*&^%!'], ['youre drunk rick!']]

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


person Matt W.    schedule 07.08.2018    source источник


Ответы (2)


Ваше сообщение об ошибке говорит вам о чем-то важном: ни словарь, ни список не могут быть хешированы, поэтому их нельзя использовать в качестве члена множества. Один из способов обойти это — использовать str, который является 0-м элементом тела письма в ваших данных.

Вы можете "uniqify" свой список на основе одного из его ключей с пониманием списка:

>>> seen = set()
>>> [i for i in rm_dict if i['body'][0] not in seen and not seen.add(i['body'][0])]
[{'name': 'rick',
  'subject': 'adventure time mortttty buugh',
  'body': ['wubba lubba dub dubbb motha f*&^%!']},
 {'name': 'morty',
  'subject': 're:adventure time mortttty buugh',
  'body': ['youre drunk rick!']}]

Вот еще одна форма, без понимания:

>>> seen = set()
>>> emails = []
>>> for i in rm_dict:
...     body = i['body'][0]
...     if body not in seen:
...         emails.append(i)
...         seen.add(body)
...         

>>> emails
[{'name': 'rick',
  'subject': 'adventure time mortttty buugh',
  'body': ['wubba lubba dub dubbb motha f*&^%!']},
 {'name': 'morty',
  'subject': 're:adventure time mortttty buugh',
  'body': ['youre drunk rick!']}]
person Brad Solomon    schedule 07.08.2018
comment
Мой пример был немного неправильным, так как мой body был списком нескольких строк, а не только 1. Поэтому преобразование его в кортеж и использование вашего кода исправили это. спасибо! - person Matt W.; 07.08.2018

Элементы набора должны быть хешируемыми, а дикты - нет. Вы можете использовать pickle для сериализации всех словарей, затем использовать set для получения уникальных элементов и, наконец, десериализовать их обратно в словари:

import pickle
print(list(map(pickle.loads, set(map(pickle.dumps, rm_dict)))))

Это выводит:

[{'name': 'morty', 'subject': 're:adventure time mortttty buugh', 'body': ['youre drunk rick!']}, {'name': 'rick', 'subject': 'adventure time mortttty buugh', 'body': ['wubba lubba dub dubbb motha f*&^%!']}]
person blhsing    schedule 07.08.2018