如何在此处更新词典列表?

时间:2014-01-11 19:13:00

标签: python

我正在尝试使用更新后的值更新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}}。

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.