Как получить уникальные значения в Python, используя понимание списка / dict

#python #python-3.x #dictionary #list-comprehension #dictionary-comprehension

#python #python-3.x #словарь #понимание списка #понимание словаря

Вопрос:

Мне нужно получить только уникальные значения из поля «город» в моем словаре. Мне нужно сделать это, используя понимание списка / dict.

 people = [ dict ( city = "Liverpool" , name = "Adam" , age = 24 ),
{ "city" : "New York" , "name" : "Dario" , "age" : 12 },
{ "city" : "New York" , "name" : "Mario" , "age" : 45 },
{ "city" : "Chicago" , "name" : "Paolo" , "age" : 27 },
{ "city" : "Brighton" , "name" : "Sven" , "age" : 19 },
{ "city" : "Berlin" , "name" : "Frank" , "age" : 52 },
{ "city" : "Rome" , "name" : "Aleksander" , "age" : 33 }
{ "city" : "Rome" , "name" : "Adam," , "age" : 24 }]
  

Я сделал это с помощью цикла таким образом:

 unique_cities = []
for x in range(len(people)):
    y = people[x]
    cities = y.get('city')
    unique_cities.append(cities)
unique_cities = list(dict.fromkeys(unique_cities))
print(unique_cities)
  

Но я раньше не имел дела с пониманием списка / dict. Я могу печатать только все значения, подобные этому:

 for x in range(len(people)):
    y = people[x]
    dict_comp = {k:v for (k, v) in y.items()}
    print(dict_comp)
  

Комментарии:

1. print( list(set(i["city"] for i in people)) )

Ответ №1:

Понимание списка и передача его в набор.

 set(person['city'] for person in people)
  

примечание: на самом деле, это выражение генератора, а не понимание списка, но в этом случае они эквивалентны для большинства целей

Комментарии:

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

2. @glhr: правильно. На самом деле, то, что я написал, не является пониманием списка.

Ответ №2:

Записи в наборе уникальны по определению, поэтому понимание набора — это именно то, что вам здесь нужно:

 {d["city"] for d in people}
  

Вывод:

 {'Berlin', 'Rome', 'Brighton', 'Liverpool', 'Chicago', 'New York'}
  

Ответ №3:

Во-первых, обратите внимание, что ваш список содержит два синтаксиса для определения словаря: dict keywords и key: value внутри accolades. Это не проблема, но это странно.

Во-вторых, в Python вам обычно не нужен индекс цикла:

 for x in range(len(people)):
    y = people[x]
    ...
  

Это то же самое , что:

 for y in people:
    ...
  

Если вам нужен индекс, у вас есть enumerate ключевое слово:

 for x, y in enumerate(people):
    ...
  

Третий:

     dict_comp = {k:v for (k, v) in y.items()}
  

создает (неглубокую) копию y и присваивает ее dict_comp . В вашем случае это не требуется:

 for y in people:
    print(y)
  

В-четвертых, dict.fromkeys это бедняга set . Оба решения примерно эквивалентны, но set теряет порядок вставки (протестировано в 3.6), тогда как dict.fromkeys сохраняет порядок вставки ключа (> = 3.6):

 >>> set(person['city'] for person in people)
{'Rome', 'Chicago', 'New York', 'Brighton', 'Liverpool', 'Berlin'}
>>> dict.fromkeys(person['city'] for person in people)
{'Liverpool': None, 'New York': None, 'Chicago': None, 'Brighton': None, 'Berlin': None, 'Rome': None}
  

Если вам нужен порядок первого появления ключа, вы также можете написать:

 >>> seen = set()
>>> [person['city'] for person in people if not (person['city'] in seen or seen.add(person['city']))]
['Liverpool', 'New York', 'Chicago', 'Brighton', 'Berlin', 'Rome']
  

Каждый раз, когда встречается новое city значение, понимание списка добавляет его в выходные данные и в seen set (осторожно: побочный эффект внутри понимания списка):

 >>> seen
{'Berlin', 'Liverpool', 'Rome', 'New York', 'Brighton', 'Chicago'}