我正在尝试使用更新后的值更新listy
;每个都是字典列表。对于更新中的每个值,如果'name'
键和'coverage'
键与listy
中的字典匹配,那么我需要更新它。如果没有,则只需将该值附加到listy
即可。 'coverage'
的顺序无关紧要;只要列表匹配。
listy = [{'name':'Dan','coverage':[{'city':'Malibu','state':'California'}],'employees':'12'},
{'name':'Emily','coverage':[{'city':'Boston','state':'Massachusetts'}],'employees':'8'},
{'name':'Martin','coverage':[{'city':'Malibu','state':'California'},{'city':'San Antonio','state':'Texas'}],'employees':'5'},
{'name':'Steve','coverage':[{'city':'Madison','state':'Wisconsin'},{'city':'Denver','state':'Colorado'}],'employees':'4'},
{'name':'Steve','coverage':[{'city':'Madison','state':'Wisconsin'}],'employees':'3'},
{'name':'Iris','coverage':[{'city':'Boise','state':'Idaho'}],'employees':'0'},
{'name':'Axl','coverage':[{'city':'Omaha','state':'Nebraska'}],'employees':'4'},
{'name':'Iris','coverage':[{'city':'New York','state':'New York'}],'employees':'7'},
{'name':'Floyd','coverage':[{'city':'Denver','state':'Colorado'}],'employees':'3'},
{'name':'Martin','employees':'5'}
]
updated = [
{'name':'Emily','coverage':[{'city':'Boston','state':'Massachusetts'}],'employees':'5'},
{'name':'Dan','coverage':[{'city':'Malibu','state':'California'}],'employees':'13'},
{'name':'Martin','coverage':[{'city':'San Antonio','state':'Texas'},{'city':'Malibu','state':'California'}],'employees':'7'},
{'name':'Steve','coverage':[{'city':'Madison','state':'Wisconsin'}],'employees':'6'},
{'name':'Steve','coverage':[{'city':'Chicago','state':'Illinois'}],'employees':'3'},
{'name':'Steve','coverage':[{'city':'Denver','state':'Colorado'},{'city':'Madison','state':'Wisconsin'}],'employees':'8'},
{'name':'Randall','coverage':[{'city':'Balmont','state':'Virginia'}],'employees':'12'},
{'name':'Rachel','employees':'1'}
]
for u in updated:
if 'coverage' in u:
u['coverage'].sort()
print 'Looking for:', u['name'],u['coverage']
match = [x for x in listy if 'coverage' in x if x['name']==u['name'] and x['coverage'].sort()==u['coverage'].sort()]
else:
print 'Looking for:', u['name']
match = [x for x in listy if 'coverage' not in x and x['name'] == u['name']]
print 'Found:', match
print '-------'
以上版画:
Looking for: Emily [{'city': 'Boston', 'state': 'Massachusetts'}]
Found: [{'employees': '8', 'name': 'Emily', 'coverage': [{'city': 'Boston', 'state': 'Massachusetts'}]}]
-------
Looking for: Dan [{'city': 'Malibu', 'state': 'California'}]
Found: [{'employees': '12', 'name': 'Dan', 'coverage': [{'city': 'Malibu', 'state': 'California'}]}]
-------
Looking for: Martin [{'city': 'Malibu', 'state': 'California'}, {'city': 'San Antonio', 'state': 'Texas'}]
Found: [{'employees': '5', 'name': 'Martin', 'coverage': [{'city': 'Malibu', 'state': 'California'}, {'city': 'San Antonio', 'state': 'Texas'}]}]
-------
Looking for: Steve [{'city': 'Madison', 'state': 'Wisconsin'}]
Found: [{'employees': '4', 'name': 'Steve', 'coverage': [{'city': 'Denver', 'state': 'Colorado'}, {'city': 'Madison', 'state': 'Wisconsin'}]}, {'employees': '3', 'name': 'Steve', 'coverage': [{'city': 'Madison', 'state': 'Wisconsin'}]}]
-------
Looking for: Steve [{'city': 'Chicago', 'state': 'Illinois'}]
Found: [{'employees': '4', 'name': 'Steve', 'coverage': [{'city': 'Denver', 'state': 'Colorado'}, {'city': 'Madison', 'state': 'Wisconsin'}]}, {'employees': '3', 'name': 'Steve', 'coverage': [{'city': 'Madison', 'state': 'Wisconsin'}]}]
-------
Looking for: Steve [{'city': 'Denver', 'state': 'Colorado'}, {'city': 'Madison', 'state': 'Wisconsin'}]
Found: [{'employees': '4', 'name': 'Steve', 'coverage': [{'city': 'Denver', 'state': 'Colorado'}, {'city': 'Madison', 'state': 'Wisconsin'}]}, {'employees': '3', 'name': 'Steve', 'coverage': [{'city': 'Madison', 'state': 'Wisconsin'}]}]
-------
Looking for: Randall [{'city': 'Balmont', 'state': 'Virginia'}]
Found: []
-------
Looking for: Rachel
Found: []
-------
正如你所看到的,史蒂夫有点搞砸了。即使'Steve'
不匹配(即使我已指定它们应匹配),它也会在listy
中获取'coverage'
len(x['coverage'])==len(u['coverage'])
。即使我在列表理解中指定listy
,它仍然是搞砸了。我究竟做错了什么?此外,即使我确实纠正了错误,我也不知道如何使用新值更新{{1}}。
答案 0 :(得分:3)
一个问题是sort()
就地操作列表并返回None
,所以这不符合您的意图:
x['coverage'].sort() == u['coverage'].sort()
请改为sorted()
。
其他一些想法和建议:
CV = 'coverage'
NM = 'name'
# If possible, make sure all of the data meets basic expectations.
# This simplifies other logic.
def normalize(bosses):
for b in bosses:
if CV not in b: b[CV] = []
if NM not in b: b[NM] = None
b[CV].sort()
normalize(listy)
normalize(updated)
def bosses_match(b1, b2):
return b1[NM] == b2[NM] and b1[CV] == b2[CV]
for u in updated:
matches = [i for i, x in enumerate(listy) if bosses_match(u, x)]
if matches:
for i in matches:
listy[i] = u
else:
listy.append(u)
请注意,如果您的列表很大,您的方法会非常慢,因为您一遍又一遍地搜索主列表。更好的方法是使用允许您快速查找匹配项的数据结构。您至少可以按名称组织数据。然后,您搜索匹配项将在更小的空间内运行。例如:
from collections import defaultdict
lookup = defaultdict(list)
for i, b in enumerate(listy):
lookup[b[NM]].append(i) # Store the item, or the index.