包含列表理解的Python字典列表

时间:2016-07-20 11:50:51

标签: python

我有一个包含列表的字典列表:

a = [{'alpha': 'a', 'val': 10, 'num': ['one', 'two']},
     {'alpha': 'b', 'val': 22, 'num': ['two']},
     {'alpha': 'c', 'val': 1, 'num': ['seven']},
     {'alpha': 'a', 'val': 10, 'num': ['three','nine']},
     {'alpha': 'b', 'val': 9, 'num': ['two', 'four']}]  

我想要的输出是:

[{'alpha': 'a', 'TotalVal': 20, num: ['one', 'two', 'three', 'nine'], 'numlen': 4}, 
 {'alpha': 'b', 'TotalVal': 31, num: ['two', 'four'], 'numlen': 2}, 
 {'alpha': 'c', 'val': 1, 'num': ['seven'], 'numlen': 1}]  

我尝试了以下内容:

sumVal = collections.defaultdict(float)
for info in a:
    sumVal[info['alpha']] += info['val']

sumVal = [{'alpha': c, 'TotalVal': sumVal[c]} for c in sumVal]  

numList = collections.defaultdict(list)
for info in a:
    numList[info['alpha']].append(info['num'])
numList = [{'alpha': k, 'num': set(v), 'len': len(set(v))} for k, v in numList.items()]  

def merge_lists(l1, l2, key):
    merged = {}
    for item in l1+l2:
        if item[key] in merged:
            merged[item[key]].update(item)
        else:
            merged[item[key]] = item
    return [val for (_, val) in merged.items()]

final = merge_lists(sumVal, numList, 'alpha')  

我没有获得numList的所需输出。得到以下错误。

  

TypeError:不可用类型:'list'

如何以较少的步骤获得所需的输出并消除错误?

5 个答案:

答案 0 :(得分:1)

试试这段代码:

a = [{'alpha':'a','val':10,'num':['one','two']},{'alpha':'b','val':22,'num':['two']},{'alpha':'c','val':1,'num':['seven']},{'alpha':'a','val':10,'num':['three','nine']},{'alpha':'b','val':9,'num':['two','four']}]

def merge_dicts(x, y):
    x.update(y)
    return x

def r(acc, x):
    if x['alpha'] in acc:
        acc[x['alpha']]['TotalVal'] += x['val']
        acc[x['alpha']]['num'] |= set(x['num'])
        acc[x['alpha']]['numlen'] = len(acc[x['alpha']]['num'])
    else:
        acc[x['alpha']] = {
            'TotalVal': x['val'],
            'num': set(x['num']),
            'numlen': len(set(x['num'])),
        }
    return acc

result = map(lambda (x, y): merge_dicts({'alpha': x}, y),
             reduce(r, a, {}).iteritems())
print(result)

答案 1 :(得分:1)

问题出在这一行:

numList[info['alpha']].append(info['num'])

将列表附加到列表中,将要附加的列表放入要附加的列表中。

我认为你想要的是延伸。

append vs. extend

答案 2 :(得分:1)

#!/usr/bin/env python

a = [{'alpha':'a','val':10,'num':['one','two', 'one', 'two']},{'alpha':'b','val':22,'num':['two']},{'alpha':'c','val':1,'num':['seven']},{'alpha':'a','val':10,'num':['three','nine']},{'alpha':'b','val':9,'num':['two','four']}]


def merge_lists(src, key):
    merged = {}
    for i in src:
        _key = i[key]
        if _key in merged:
            merged[_key]['TotalVal'] += i['val']
            merged[_key]['num'].extend(i['num'])
            merged[_key]['num'] = list(set(i['num']))
            merged[_key]['numlen'] = len(merged[_key]['num'])
        else:
            merged[_key] = {'TotalVal': i['val'], 'alpha': i['alpha'], 'num': i['num'], 'numlen': 1}

    return [val for (_, val) in merged.items()]


final = merge_lists(a, 'alpha')

print(final)

输出: [{'alpha':'a','TotalVal':20,'num':['nine','three'],'numlen':2},{'alpha':'c','TotalVal': 1,'num':['seven'],'numlen':1},{'alpha':'b','TotalVal':31,'num':['four','two'],'numlen ':2}]

答案 3 :(得分:1)

不像其他答案那么短,但实施简单

a = [{'alpha':'a','val':10,'num':['one','two']},
    {'alpha':'b','val':22,'num':['two']},
    {'alpha':'c','val':1,'num':['seven']},
    {'alpha':'a','val':10,'num':['three','nine']},
    {'alpha':'b','val':9,'num':['two','four']}] 

new_list = []

# Loop through entries
for entry in a:
    # Store first entries
    if entry['alpha'] not in [i['alpha'] for i in new_list]:
        new_dict = {'alpha': entry['alpha'],
                    'TotalVal': entry['val'],
                    'num': entry['num'],
                    'numlen': len(entry['num'])}
        new_list.append(new_dict)
        continue

    # Add in additional entries
    for i, n in enumerate(new_list):
        if n['alpha'] == entry['alpha']:
            entry_vals = entry.values()
            new_list[i]['TotalVal'] = new_list[i]['TotalVal'] + entry['val']
            new_list[i]['num'] = new_list[i]['num'] + entry['num']
            new_list[i]['numlen'] = len(new_list[i]['num'])

# filter final data
for i, n in enumerate(new_list):
    # Remove duplicate entries in num
    for entry in n['num']:
        if n['num'].count(entry) > 1:
            new_list[i]['num'].remove(entry)

    # Update numlen
    new_list[i]['numlen'] = len(new_list[i]['num'])

print new_list

答案 4 :(得分:1)

这是我提出的最简单的解决方案:

a = [{'alpha':'a','val':10,'num':['one','two']},
     {'alpha':'b','val':22,'num':['two']},
     {'alpha':'c','val':1,'num':['seven']},
     {'alpha':'a','val':10,'num':['three','nine']},
     {'alpha':'b','val':9,'num':['two','four']}] 

a2 = []
alphas = set(d['alpha'] for d in a)
for alpha in alphas:
    TotalVal, num, numlen = 0, set(), 0
    for d in a:
        if d['alpha'] == alpha:
            TotalVal += d['val']
            num = num | set(d['num'])
            numlen += 1
    new_dict = {'alpha': alpha, 'num': list(num), 'numlen': numlen}
    if numlen > 1:
        new_dict['TotalVal'] = TotalVal
    else:
        new_dict['val'] = TotalVal
    a2.append(new_dict)

演示:

>>> for d in a2: print(d)
{'alpha': 'a', 'num': ['three', 'nine', 'two', 'one'], 'numlen': 2, 'TotalVal': 20}
{'alpha': 'c', 'num': ['seven'], 'numlen': 1, 'val': 1}
{'alpha': 'b', 'num': ['four', 'two'], 'numlen': 2, 'TotalVal': 31}