#python #list #dictionary #if-statement
#python #Список #словарь #if-оператор
Вопрос:
Я постараюсь быть как можно более кратким.
Два списка словарей следующим образом:
dictlist1 = [{'name': 'john', 'age': 30}, {'name': 'jessica', 'age': 56}, {'name': 'kirk', 'age': 20}, {'name': 'mario, 'age': 25}]
dictlist2 = [{'name': 'john', 'job': 'engineer'}, {'name': 'jessica', 'job':'nurse'}, {'name': 'mario', 'job': 'electrician'}]
Моя цель — сопоставить базу по ключу «name» в обоих словарях и, в конце, создать третий список словарей с ключом, который не имеет совпадения, в данном случае {‘name’:’kirk’, ‘age’:20}, вот так:
listfinal = [{'name': 'kirk', 'age': 20}]
Я успешно попытался сравнить равные ключи, создав новый словарь с соответствующими ключами и добавив к нему ключ «job», выполнив это:
for dict2 in dictlist2:
for dict1 in dictlist1:
if dict1['name'] == dict2['name']:
matchname1 = dict2['name']
dictoutput = {'name': matchname1, 'age': dict1['age'], 'group': dict2['group']}
templist.append(dictoutput)
for dictionay in templist:
print(dictionay)
Output:
{'name': 'john', 'age': '30', 'job': 'engineer'}
{'name': 'jessica', 'age': '56', 'job': 'nurse'}
{'name': 'mario', 'age': '25', 'job': 'electrician'}
Но абсолютно не повезло получить пользователя kirk в одиночку, даже не используя «else» во внутреннем операторе if или создавая новый оператор if и используя not equal (!=). Я всегда получаю всех пользователей при печати.
Любая ориентация будет высоко оценена.
Комментарии:
1. Составьте список всех имен, которые появляются в обоих (что вы почти сделали); тогда любые имена, отсутствующие в этом списке, — это те, которые вам нужны.
2. Ваши определения
dictlist1
иdictlist2
недопустимы для Python.3. Спасибо, @ScottHunter. Я внесу соответствующие исправления! Это было использовано в качестве примера, но я понимаю суть.
Ответ №1:
Перечислите списки, а затем соберите индексы совпадающих пар в списке внутри цикла и удалите соответствующие элементы вне цикла.
matched_d1 = []
matched_d2 = []
for j2, dict2 in enumerate(dictlist2):
for j1, dict1 in enumerate(dictlist1):
if dict1['name'] == dict2['name']:
matchname1 = dict2['name']
dictoutput = {'name': matchname1, 'age': dict1['age'], 'group': dict2['group']}
templist.append(dictoutput)
matched_d1.append(j1)
matched_d2.append(j2)
for j in sorted(matched_d1, reverse = True):
dictlist1.pop(j)
for j in sorted(matched_d2, reverse = True):
dictlist2.pop(j)
ans = dictlist1 dictlist2
Комментарии:
1. Большое спасибо, @freude! Это было идеально для понимания индекса списка, в котором находится «другой» словарь.
Ответ №2:
Вы можете использовать sets
для поиска имен, которые есть только в dictlist1
, в dictlist2
, а также общих имен. Затем создайте listfinal
, сохранив только элемент с name
не в общих именах:
dictlist1 = [{"name": "john", "age": 30}, {"name": "jessica", "age": 56}, {"name":"kirk" , "age": 20}, {"name": "mario", "age": 25}]
dictlist2 = [{"name": "john", "job": "engineer"}, {"name": "jessica", "job": "nurse"}, {"name": "mario", "job": "electrician"}]
names_dictlist1 = {item["name"] for item in dictlist1}
names_dictlist2 = {item["name"] for item in dictlist2}
common_names = names_dictlist1 amp; names_dictlist2
listfinal = [item for item in dictlist1 dictlist2 if item["name"] not in common_names]
Комментарии:
1. БОЖЕ … это сделало трюк.! Очень признателен! Я так много раз пробовал цикл, что забыл о реальной проблеме… Я полностью отбросил логику, стоящую за последней строкой!
Ответ №3:
Если вам нужно однострочное решение, оно есть
print([person for person in dictlist1 if person['name'] not in map(lambda x: x['name'], dictlist2)])
Этот код выводит элемент из первого списка, ключ «name» которого не встречается во втором списке
Комментарии:
1. Еще одна отличная строка, которая позволяет этому работать! Это так просто и аккуратно. Спасибо!
Ответ №4:
вы можете использовать операции набора для получения уникального имени, сначала создайте набор имен для каждого из них и вычтите оба, затем используйте это, чтобы получить соответствующий элемент из списка
>>> name1 = set(d["name"] for d in dictlist1)
>>> name2 = set(d["name"] for d in dictlist2)
>>> name1 - name2
{'kirk'}
>>> name2 - name1
set()
>>> unique = name1 - name2
>>> listfinal = [d for n in unique for d in dictlist1 if d["name"]==n]
>>> listfinal
[{'name': 'kirk', 'age': 20}]
>>>
Кроме того, глядя на ответы @freude, вы можете сделать его словарем name:index для каждого списка, который вычитает его ключи, учитывая, что они dict.keys ведут себя как набор, чтобы избежать двойного цикла, предшествующего получению нужного элемента из списка
>>> name1 = {d["name"]:i for i,d in enumerate(dictlist1)}
>>> name2 = {d["name"]:i for i,d in enumerate(dictlist2)}
>>> unique = name1.keys() - name2.keys()
>>> unique
{'kirk'}
>>> [ dictlist1[name1[n]] for n in unique]
[{'name': 'kirk', 'age': 20}]
>>>
Комментарии:
1. Это не приведет к перехвату «совпадающих» имен
dictlist2
.2. @ScottHunter просто сделайте то же самое для другого случая, просто поменяйте местами роль dictlist1 и dictlist2
3. Еще один способ сделать это. Спасибо @Cooperfield! Учусь у всех вас, ребята.