Python:dict中的组列表项

Erw*_*lec 13 python algorithm dictionary group-by

我想从字典列表生成一个字典,按一些键的值对列表项进行分组,例如:

input_list = [
        {'a':'tata', 'b': 'foo'},
        {'a':'pipo', 'b': 'titi'},
        {'a':'pipo', 'b': 'toto'},
        {'a':'tata', 'b': 'bar'}
]
output_dict = {
        'pipo': [
             {'a': 'pipo', 'b': 'titi'}, 
             {'a': 'pipo', 'b': 'toto'}
         ],
         'tata': [
             {'a': 'tata', 'b': 'foo'},
             {'a': 'tata', 'b': 'bar'}
         ]
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已经找到了两种方法.第一个简单地遍历列表,在dict中为每个键值创建子列表,并将匹配这些键的元素附加到子列表:

l = [ 
    {'a':'tata', 'b': 'foo'},
    {'a':'pipo', 'b': 'titi'},
    {'a':'pipo', 'b': 'toto'},
    {'a':'tata', 'b': 'bar'}
    ]

res = {}

for e in l:
    res[e['a']] = res.get(e['a'], []) 
    res[e['a']].append(e)
Run Code Online (Sandbox Code Playgroud)

而另一个使用itertools.groupby:

import itertools
from operator import itemgetter

l = [ 
        {'a':'tata', 'b': 'foo'},
        {'a':'pipo', 'b': 'titi'},
        {'a':'pipo', 'b': 'toto'},
        {'a':'tata', 'b': 'bar'}
]

l = sorted(l, key=itemgetter('a'))
res = dict((k, list(g)) for k, g in itertools.groupby(l, key=itemgetter('a')))
Run Code Online (Sandbox Code Playgroud)

我想知道哪种替代方案效率最高?

是否有更多的pythonic /简洁或更好的表现方式来实现这一目标?

Ber*_*ard 14

您是否希望按列表元素的"a"键的值对输入列表进行分组?如果是这样,你的第一种方法是最好的,一个小改进,使用dict.setdefault:

res = {}
for item in l:
    res.setdefault(item['a'], []).append(item)
Run Code Online (Sandbox Code Playgroud)


小智 8

如果高效是指“时间高效”,则可以使用timeit内置模块进行测量。

例如:

import timeit
import itertools
from operator import itemgetter

input = [{'a': 'tata', 'b': 'foo'},
         {'a': 'pipo', 'b': 'titi'},
         {'a': 'pipo', 'b': 'toto'},
         {'a': 'tata', 'b': 'bar'}]

def solution1():
    res = {}
    for e in input:
        res[e['a']] = res.get(e['a'], [])
        res[e['a']].append(e)
    return res

def solution2():
    l = sorted(input, key=itemgetter('a'))
    res = dict(
        (k, list(g)) for k, g in itertools.groupby(l, key=itemgetter('a'))
    )
    return res

t = timeit.Timer(solution1)
print(t.timeit(10000))
# 0.0122511386871

t = timeit.Timer(solution2)
print(t.timeit(10000))
# 0.0366218090057
Run Code Online (Sandbox Code Playgroud)

请参阅timeit 官方文档以获取更多信息。


Ana*_*mar 5

一班轮-

>>> import itertools
>>> input_list = [
...         {'a':'tata', 'b': 'foo'},
...         {'a':'pipo', 'b': 'titi'},
...         {'a':'pipo', 'b': 'toto'},
...         {'a':'tata', 'b': 'bar'}
... ]
>>> {k:[v for v in input_list if v['a'] == k] for k, val in itertools.groupby(input_list,lambda x: x['a'])}
{'tata': [{'a': 'tata', 'b': 'foo'}, {'a': 'tata', 'b': 'bar'}], 'pipo': [{'a': 'pipo', 'b': 'titi'}, {'a': 'pipo', 'b': 'toto'}]}
Run Code Online (Sandbox Code Playgroud)