从dicts列表中以pythonic方式获取每个键的最大值

时间:2015-11-10 16:31:26

标签: python python-3.x list-comprehension

我正在寻找一种更加pythonic的方法来获取字典列表中每个键的最大值。

我的方法看起来像这样

lst =[{'a':'asdasd', 'b': 123},{'a': 'asdasdasdas'}, {'a':123,'b':'asdasd'}]
dct = {}
for l in lst:
    for key in l:
        dct.update({key: max(dct.get(key,0), len(str(l.get(key,0))))})
print(dct)

输出结果

  

{'b':6,'a':11}

需要str函数来获得整数的长度(以及Nones)

这种方法是“pythonic”还是使用列表推导或类似方法更流畅,更易读。

5 个答案:

答案 0 :(得分:2)

我认为你的方法是相当Pythonic的,除非我将update行更改为更清晰:

# A little terse
dct.update({key: max(dct.get(key,0), len(str(l.get(key,0))))})
# A little simpler
dct[key] = max(dct.get(key, 0), len(str(l[key])))

这是一个修改了变量名称的解决方案:

dict_list =[{'a':'asdasd', 'b': 123},{'a': 'asdasdasdas'}, {'a':123,'b':'asdasd'}]
max_lengths = {}
for dictionary in dict_list:
    for k, v in dictionary.items():
        max_lengths[k] = max(max_lengths.get(k, 0), len(str(v)))
print(max_lengths)

答案 1 :(得分:1)

我之前的回答是错误的,并没有意识到,但这里有两个其他的工作。第一个使用熊猫。它创建一个数据帧,对键进行排序,然后对值进行排序,获取每个组的第一个值,然后创建一个字典

import pandas as pd
lst = [{'a':'asdasd', 'b': 123},{'a': 'asdasdasdas'}, {'a':123,'b':'asdasd'}]
dct={}

d = pd.DataFrame([(k,len(str(v))) for i in lst for k,v in i.items()], columns=['Key','Value'])
d = d.sort(['Key','Value'], ascending=[1,0])
d = d.groupby('Key').first().reset_index()
d = dict(zip(d.Key, d.Value))  #or d.set_index('Key')['Value'].to_dict()
print d

{'a': 11, 'b': 6}

如果你想要一些易于阅读并使用内置模块的东西,那么这应该

lst = [{'a':'asdasd', 'b': 123},{'a': 'asdasdasdas'}, {'a':123,'b':'asdasd'}]
dct={}

for i in lst:
    for k,v in i.items():
        if k in dct:
            if len(str(v)) > dct[k]:
                dct[k] = len(str(v))
        else:
            dct[k] = len(str(v))
print dct

{'a': 11, 'b': 6}

答案 2 :(得分:1)

这是另一种不依赖于排序/压缩的方式,但我不会说一个人比另一个人更像Pythonic。

from itertools import chain

lst =[{'a':'asdasd', 'b': 123}, {'a': 'asdasdasdas'}, {'a':123,'b':'asdasd'}]
dct = {
    k: max(len(str(d.get(k, ""))) for d in lst)
    for k in set(chain.from_iterable(d.keys() for d in lst))
}

print(dct)

或者,您可以使用groupby:

from itertools import chain, groupby

lst =[{'a':'asdasd', 'b': 123}, {'a': 'asdasdasdas'}, {'a':123,'b':'asdasd'}]
dct = {
    k: max(len(str(v)) for _, v in g)
    for k, g in groupby(
        chain.from_iterable(d.items() for d in lst),
        lambda p: p[0]
    )
}

print(dct)

答案 3 :(得分:1)

其他答案侧重于使用python功能而不是可读性。我个人认为可读性和简洁性是所有“pythonic”中最重要的。性状。

(我简化为所有内容都使用字符串,但如果你放入str()那么它也适用于整数)

from collections import defaultdict

lst =[{'a':'asdasd', 'b': '123'},{'b': 'asdasdasdas'}, {'a':'123','b':'asdasd'}]

def merge_dict(dic1,dic2) :
    for key,value in dic2.items():
            dic1[key].append(value)

combined = defaultdict(list)
for dic in lst:
    merge_dict(combined, dic)

print( {key : max(map(len,value)) for key, value in combined.items() } )

答案 4 :(得分:1)

我喜欢这种方式以便于阅读和使用Python:

dicts = [{'a':'asdasd', 'b': 123},{'a': 'asdasdasdas'}, {'a':123,'b':'asdasd'}]

def get_highest(current_highest, items_left):
    if not items_left:
        return current_highest
    else:
        item = items_left.pop()
        higher = {key: len(str(value)) for key, value in item.items() if (len(str(item[key])) > current_highest.get(key, 0))}
    if higher:
        current_highest.update(higher)
    return get_highest(current_highest, items_left)

print(get_highest(dict(), dicts))

{'b': 6, 'a': 11}