2013-02-12 150 views
4

我一直在努力奋斗几个小时,以解决以下问题,但未取得成功。将字典列表转换为唯一的字典列表

我有一个数据结构,看起来像这样:

[ { 'ROOT': [ 
      { 'firstElem': 'gc-3/1/0'}, 
      { 'SecondElem': '5.0.0.1'}, 
      { 'ThirdElem': '127.3.15.1'}, 
      { 'index': 16}, 
      { 'function': 'session'}, 
      { 'hw': '0.0.0.0'}, 
      { 'sw': '1.50.1.3'}, 
      { 'resources': [ { 'cpu-info': [ { 'cpu-peak-load': 1}, 
                { 'cpu-avg-load': 1}]}, 
           { 'memory-total': 1}, 
           { 'memory-used': 2}]}, 
      ]}, 
    { 'ROOT': [ 
      { 'firstElem': 'gc-4/1/0'}, 
      { 'SecondElem': '5.0.0.2'}, 
      { 'ThirdElem': '127.3.4.1'}, 
      { 'index': 5}, 
      { 'function': 'stand'}, 
      { 'hw': '0.0.0.0'}, 
      { 'sw': '1.50.1.3'}, 
      { 'resources': [ { 'cpu-info': [ { 'cpu-peak-load': 1}, 
                { 'cpu-avg-load': 1}]}, 
           { 'memory-total': 1}, 
           { 'memory-used': 2}]}, 
      ]} 
] 

我想遍历这个数据结构,并使用相同的名称将所有的字典元素,并创建一个列表来代替。 这是很难解释,我已经创造了什么,我想找一个示例结构:

{ 
    "ROOT": [ 
     { 
      "firstElem": "gc-3/1/0", 
      "SecondElem": "5.0.0.1", 
      "ThirdElem": "128.0.2.19", 
      "index": "13", 
      "function": "session", 
      "hw": "1.11.0.0 ", 
      "sw": "1.50.0.228 ", 
      "resources": { 
       "cpu-info": { 
        "cpu-peak-load": "1", 
        "cpu-avg-load": "1", 
       }, 
       "memory-total": "1", 
       "memory-used": "2", 
      }, 
     }, 
     { 
      "firstElem": "gc-4/1/0", 
      "SecondElem": "5.0.0.1", 
      "ThirdElem": "128.0.2.19", 
      "index": "13", 
      "function": "session", 
      "hw": "1.11.0.0 ", 
      "sw": "1.50.0.228 ", 
      "resources": { 
       "cpu-info": { 
        "cpu-peak-load": "8", 
        "cpu-avg-load": "1", 
       }, 
       "memory-total": "1", 
       "memory-used": "2", 
      }, 
     } 
    ], 
} 

我坚持与原始数据结构和不能改变它。任何帮助表示赞赏。 上面提供的结构只是一个例子,因为数据是动态接收的,我不会知道标签名称。所以请不要提供使用特定标签名称的解决方案。

回答

2

这里有一个办法:

>>> from collections import defaultdict 
>>> def combine(item): 
    # Easy return if not a list: element itself 
    if type(item) != type([]): 
     return item 
    # else call recursion 
    first_ret = [(i.items()[0][0], combine(i.items()[0][1])) for i in item] 

    # Here we group by same keys if any ('ROOT', for instance) 
    count_keys = defaultdict(list) 
    for couple in first_ret: 
     count_keys[couple[0]].append(couple[1]) 
    return dict((k, v if len(v) > 1 else v[0]) for k, v in count_keys.iteritems()) 

我只好组ROOT节点,但它似乎是工作:

>>> pprint(combine(l)) 
{'ROOT': [{'SecondElem': '5.0.0.1', 
      'ThirdElem': '127.3.15.1', 
      'firstElem': 'gc-3/1/0', 
      'function': 'session', 
      'hw': '0.0.0.0', 
      'index': 16, 
      'resources': {'cpu-info': {'cpu-avg-load': 1, 
             'cpu-peak-load': 1}, 
         'memory-total': 1, 
         'memory-used': 2}, 
      'sw': '1.50.1.3'}, 
      {'SecondElem': '5.0.0.2', 
      'ThirdElem': '127.3.4.1', 
      'firstElem': 'gc-4/1/0', 
      'function': 'stand', 
      'hw': '0.0.0.0', 
      'index': 5, 
      'resources': {'cpu-info': {'cpu-avg-load': 1, 
             'cpu-peak-load': 1}, 
         'memory-total': 1, 
         'memory-used': 2}, 
      'sw': '1.50.1.3'}]} 
>>> 
2

让我们试试这个:

r = {} 

def lst2dct(lst): 
    return (lst if not isinstance(lst, list) else 
     {k: lst2dct(v) for e in lst for k, v in e.items()}) 

for e in source: 
    key, val = e.items()[0] 
    r.setdefault(key, []).append(lst2dct(val)) 
+0

用真实代码测试,它不是工作,它似乎只采取一个根元素,第二个不知何故被丢弃! – theAlse 2013-02-13 09:28:21

+0

@theAlse:在某处发布实际数据(例如gist.github.com) – georg 2013-02-13 09:46:37

1

它有点哈克,但你可以尝试:

data = [ { 'ROOT': [ 
      { 'firstElem': 'gc-3/1/0'}, 
      { 'SecondElem': '5.0.0.1'}, 
      { 'ThirdElem': '127.3.15.1'}, 
      { 'index': 16}, 
      { 'function': 'session'}, 
      { 'hw': '0.0.0.0'}, 
      { 'sw': '1.50.1.3'}, 
      { 'resources': [ { 'cpu-info': [ { 'cpu-peak-load': 1}, 
                { 'cpu-avg-load': 1}]}, 
           { 'memory-total': 1}, 
           { 'memory-used': 2}]}, 
      ]}, 
    { 'ROOT': [ 
      { 'firstElem': 'gc-4/1/0'}, 
      { 'SecondElem': '5.0.0.2'}, 
      { 'ThirdElem': '127.3.4.1'}, 
      { 'index': 5}, 
      { 'function': 'stand'}, 
      { 'hw': '0.0.0.0'}, 
      { 'sw': '1.50.1.3'}, 
      { 'resources': [ { 'cpu-info': [ { 'cpu-peak-load': 1}, 
                { 'cpu-avg-load': 1}]}, 
           { 'memory-total': 1}, 
           { 'memory-used': 2}]}, 
      ]} 
] 

root_list = [ 

     ] 

final_data = { 
      'ROOT' : root_list 
      } 

for dict in data: 
    if dict['ROOT'] not in final_data['ROOT']: 
     final_data['ROOT'].append(dict['ROOT']) 
+0

请参阅已编辑的问题,我不能使用特定的标签名称,这仅仅是一个示例。 – theAlse 2013-02-12 17:26:06

0

我只是做了一些在这里和那里的东西的解释,并拿出了这一点:

>>> i = [...] # your data 
>>> rdict = {} 
>>> for di in i: 
for root in di: 
    if root not in rdict: 
     rdict[root] = [di[root]] 
    else: 
     rdict[root] += [di[root]] 

rdict字典是你所需要的类型,应该多升工作派。


这个功能版本:

def common_dict(list_of_dicts): 
    i = list_of_dicts # less typing 
    rdict = {} 
    for di in i: 
     for root in di: 
      if root not in rdict: 
       rdict[root] = [di[root]] 
      else: 
       rdict[root] += [di[root]] 
return rdict