2014-12-19 75 views
1

我想結合使用同一個密鑰的字典列表。我要做的結果是具有唯一「Org_ID」的字典列表。所有「範圍」相同的「Org_ID」將在列表中的單個字典中。這裏是我的原始數據:使用此結合使用同一密鑰的字典列表

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」 只包含一個

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 = dict([(k, [orig_data[k]]) for k in orig_data]) 

但不工作或者。我假設它是因爲它尋找一個單一的字典而不是一系列的字典?

+0

看起來你需要'ipcalc'模塊,以幫助您評估在'dict's'值所使用的那些字符串? –

回答

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']}] 
+0

如果我不想讓每個字典中的'範圍'成爲列表,我需要改變什麼?這意味着所有的數據都將保留,它不會是一個列表。 – nousername

+0

你可以使用'set'(你會失去任何重複的東西,然後你可能想用'collections.Counter')。但最終,你需要一些收集。你爲什麼不願意使用列表? – inspectorG4dget

+0

我試過設置,也不工作。原因是接受這些數據的代碼需要像'172.16.0.1-172.16.0.254','172.16.3.1-172.16.3.254'這樣的輸入,而不是一個列表。 – nousername

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"] 
+0

bah太快了:P ...很好的答案; P –

+1

@JoranBeasley,犯了一個錯誤,我想盡管op想要一個dicts列表! –

+0

ahh我看到了......哦,很好 –

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'}] 
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()) 
相關問題