将词典列表与相同的键组合在一起

时间:2014-12-19 20:58:25

标签: python dictionary

我正在尝试将一个字典列表与相同的键组合在一起。我想要的结果是具有唯一“Org_ID”的字典列表。相同“Org_ID”的所有“范围”将在列表中的单个字典中。这是我的原始数据:

orig_data = [{'Range': '192.168.1.1-192.168.1.254', 'Org_ID': 'TX', 'name': 'TX-Dallas'}, 
             {'Range': '192.168.2.1-192.168.2.254', 'Org_ID': 'TX', 'name': 'TX-Dallas'}, 
             {'Range': '192.168.3.1-192.168.3.254', 'Org_ID': 'TX', 'name': 'TX-Dallas'}, 
             {'Range': '10.0.0.1-10.0.0.254', 'Org_ID': 'TX', 'name': 'TX-Dallas'}, 
             {'Range': '192.168.9.1-192.168.1.254', 'Org_ID': 'CA', 'name': 'CA-San Diego'}, 
             {'Range': '10.0.5.1-10.0.5.254', 'Org_ID': 'CA', 'name': 'CA-San Diego'}, 
             {'Range': '172.16.0.1-172.16.0.254', 'Org_ID': 'TX', 'name': 'TX-Houston'}, 
             {'Range': '172.16.3.1-172.16.3.254', 'Org_ID': 'TX', 'name': 'TX-Houston'}]

我想要的是什么:

new_data = [{'Range': ['192.168.1.1-192.168.1.254','192.168.2.1-192.168.2.254','192.168.3.1-192.168.3.254','10.0.0.1-10.0.0.254'] 'Org_ID': 'TX', 'name': 'TX-Dallas'}, 
            {'Range': ['192.168.9.1-192.168.1.254','10.0.5.1-10.0.5.254'] 'Org_ID': 'CA', 'name': 'CA-San Diego'}, 
            {'Range': ['172.16.0.1-172.16.0.254','172.16.3.1-172.16.3.254'] 'Org_ID': 'TX', 'name': 'TX-Houston'}]

我试图用这个来做:

d = defaultdict(dict)
for i in (orig_data):
  for elem in orig_data:
    d[elem['Org_ID']].update(elem)
new_data = d.values()

但是“new_data”只包含一个字典。

我也尝试过这样做:

new_data = dict([(k, [orig_data[k]]) for k in orig_data])

但这也不起作用。我假设是因为它寻找单个词典而不是词典列表?

4 个答案:

答案 0 :(得分:1)

orig_data = [{'Range': '192.168.1.1-192.168.1.254', 'Org_ID': 'TX', 'name': 'TX-Dallas'}, {'Range': '192.168.2.1-192.168.2.254', 'Org_ID': 'TX', 'name': 'TX-Dallas'}, {'Range': '192.168.3.1-192.168.3.254', 'Org_ID': 'TX', 'name': 'TX-Dallas'}, {'Range': '10.0.0.1-10.0.0.254', 'Org_ID': 'TX', 'name': 'TX-Dallas'}, {'Range': '192.168.9.1-192.168.1.254', 'Org_ID': 'CA', 'name': 'CA-San Diego'}, {'Range': '10.0.5.1-10.0.5.254', 'Org_ID': 'CA', 'name': 'CA-San Diego'}, {'Range': '172.16.0.1-172.16.0.254', 'Org_ID': 'TX', 'name': 'TX-Houston'}, {'Range': '172.16.3.1-172.16.3.254', 'Org_ID': 'TX', 'name': 'TX-Houston'}]

from collections import defaultdict

from itertools import groupby

res = []
for key, vals in groupby(orig_data, lambda x: (x["Org_ID"], x["name"])):
    res.append(defaultdict(list))
    for d in vals:
        for k, v in d.iteritems():
            if k == "Range":
                res[-1][k].append(v)
            else:
                res[-1][k] = v
[defaultdict(<type 'list'>, {'Range': ['192.168.1.1-192.168.1.254', '192.168.2.1-192.168.2.254', '192.168.3.1-192.168.3.254', '10.0.0.1-10.0.0.254'], 'Org_ID': 'TX', 'name': 'TX-Dallas'}),
 defaultdict(<type 'list'>, {'Range': ['192.168.9.1-192.168.1.254', '10.0.5.1-10.0.5.254'], 'Org_ID': 'CA', 'name': 'CA-San Diego'}),
 defaultdict(<type 'list'>, {'Range': ['172.16.0.1-172.16.0.254', '172.16.3.1-172.16.3.254'], 'Org_ID': 'TX', 'name': 'TX-Houston'})]

如果您想对密钥进行硬编码,可以缩短代码:

from collections import defaultdict

from itertools import groupby

res = []
for key, vals in groupby(orig_data, lambda x: (x["Org_ID"], x["name"])):
    res.append(defaultdict(list))
    for d in vals:
        res[-1]["Range"].append(d["Range"])
    res[-1]['Org_ID'] = d['Org_ID']
    res[-1]["name"] = d["name"]

答案 1 :(得分:0)

orig_data = [{'Range': '192.168.1.1-192.168.1.254', 'Org_ID': 'TX', 'name': 'TX-Dallas'}, {'Range': '192.168.2.1-192.168.2.254', 'Org_ID': 'TX', 'name': 'TX-Dallas'}, {'Range': '192.168.3.1-192.168.3.254', 'Org_ID': 'TX', 'name': 'TX-Dallas'}, {'Range': '10.0.0.1-10.0.0.254', 'Org_ID': 'TX', 'name': 'TX-Dallas'}, {'Range': '192.168.9.1-192.168.1.254', 'Org_ID': 'CA', 'name': 'CA-San Diego'}, {'Range': '10.0.5.1-10.0.5.254', 'Org_ID': 'CA', 'name': 'CA-San Diego'}, {'Range': '172.16.0.1-172.16.0.254', 'Org_ID': 'TX', 'name': 'TX-Houston'}, {'Range': '172.16.3.1-172.16.3.254', 'Org_ID': 'TX', 'name': 'TX-Houston'}]

cont = collections.defaultdict(lambda : collections.defaultdict(list))
for d in orig_data:
    cont[d['Org_ID']][d['name']].append(d['Range'])

answer = []
for orgid in cont:
    for name,rangelist in cont[orgid].items():
        answer.append({'Org_ID':orgid, 'name':name, 'Range':rangelist})

输出:

In [226]: answer
Out[226]: 
[{'name': 'TX-Houston',
  'Org_ID': 'TX',
  'Range': ['172.16.0.1-172.16.0.254', '172.16.3.1-172.16.3.254']},
 {'name': 'TX-Dallas',
  'Org_ID': 'TX',
  'Range': ['192.168.1.1-192.168.1.254',
   '192.168.2.1-192.168.2.254',
   '192.168.3.1-192.168.3.254',
   '10.0.0.1-10.0.0.254']},
 {'name': 'CA-San Diego',
  'Org_ID': 'CA',
  'Range': ['192.168.9.1-192.168.1.254', '10.0.5.1-10.0.5.254']}]

答案 2 :(得分:0)

from collections import defaultdict

new_data = defaultdict(lambda: [])

for entry in orig_data:
    key = (entry["Org_ID"], entry["name"])
    new_data[key].append(entry["Range"])

res = [{"Org_ID":k[0], "name":k[1], "Range":v} for k,v in new_data.items()]

那样:

>>> res
[{'Org_ID': 'TX',
  'Range': ['172.16.0.1-172.16.0.254', '172.16.3.1-172.16.3.254'],
  'name': 'TX-Houston'},
 {'Org_ID': 'CA',
  'Range': ['192.168.9.1-192.168.1.254', '10.0.5.1-10.0.5.254'],
  'name': 'CA-San Diego'},
 {'Org_ID': 'TX',
  'Range': ['192.168.1.1-192.168.1.254',
   '192.168.2.1-192.168.2.254',
   '192.168.3.1-192.168.3.254',
   '10.0.0.1-10.0.0.254'],
  'name': 'TX-Dallas'}]

答案 3 :(得分:0)

尝试:

keys = ('Org_ID', 'name', 'Range')
new_data = {}

for d in orig_data:
    o, n, r = (d[k] for k in keys)
    if o not in new_data:
        new_data[o] = dict(zip(keys, (o, n, [r])))
    else:
        new_data[o]['Range'].append(r)

new_data = list(new_data.values())