合并版本化词典的数组

时间:2014-02-25 21:40:44

标签: python arrays dictionary merge

鉴于以下两个字典数组,我如何合并它们,以便生成的字典数组只包含那些 version 最大的字典?

data1 = [{'id': 1, 'name': u'Oneeee', 'version': 2},
         {'id': 2, 'name': u'Two', 'version': 1},
         {'id': 3, 'name': u'Three', 'version': 2},
         {'id': 4, 'name': u'Four', 'version': 1},
         {'id': 5, 'name': u'Five', 'version': 1}]

data2 = [{'id': 1, 'name': u'One', 'version': 1},
         {'id': 2, 'name': u'Two', 'version': 1},
         {'id': 3, 'name': u'Threeee', 'version': 3},
         {'id': 6, 'name': u'Six', 'version': 2}]

合并的结果应如下所示:

data3 = [{'id': 1, 'name': u'Oneeee', 'version': 2},
         {'id': 2, 'name': u'Two', 'version': 1},
         {'id': 3, 'name': u'Threeee', 'version': 3},
         {'id': 4, 'name': u'Four', 'version': 1},
         {'id': 5, 'name': u'Five', 'version': 1},
         {'id': 6, 'name': u'Six', 'version': 2}]

2 个答案:

答案 0 :(得分:3)

如果您想根据词典id获得最高版本,那么您可以使用itertools.groupby这样的方法:

sdata = sorted(data1 + data2, key=lambda x:x['id'])
res = []
for _,v in itertools.groupby(sdata, key=lambda x:x['id']):
    v = list(v)
    if len(v) > 1:    # happened that the same id was in both datas
        # append the one with higher version
        res.append(v[0] if v[0]['version'] > v[1]['version'] else v[1])
    else:             # the id was in one of the two data
        res.append(v[0])

解决方案不是单行,但我认为很简单(一旦你理解groupby()这不是一件容易的事。)

这将导致res包含此列表:

[{'id': 1, 'name': u'Oneeee', 'version': 2},
 {'id': 2, 'name': u'Two', 'version': 1},
 {'id': 3, 'name': u'Threeee', 'version': 3},
 {'id': 4, 'name': u'Four', 'version': 1},
 {'id': 5, 'name': u'Five', 'version': 1},
 {'id': 6, 'name': u'Six', 'version': 2}]

我认为可以缩小解决方案,但可能很难理解。

希望这有帮助!

答案 1 :(得分:1)

一个相当简单的程序解决方案,我们构建一个按项目ID键入的字典,然后替换项目:

indexed_data = { item['id']: item for item in data1 }
# or, pre-Python2.7:
# indexed_data = dict((item['id'], item) for item in data1)
for item in data2:
    if indexed_data.get(item['id'], {'version': float('-inf')})['version'] < item['version']:
        indexed_data[item['id']] = item
data3 = [item for (_, item) in sorted(indexed_data.items())]

同样的事情,但使用更实用的方法:

sorted_items = sorted(data1 + data2, key=lambda item: (item['id'], item['version']))
merged = { item['id']: item for item in sorted_items }
# or, pre-Python2.7:
# merged = dict((item['id'], item) for item in sorted_items )
data3 = [item for (_, item) in sorted(merged.items())]