我有一个列表[a1,21,...]
,并希望根据函数f(a)
的值对其进行拆分。
例如,如果输入是列表[0,1,2,3,4]
和函数def f(x): return x % 3
,
我想返回一个列表[0,3], [1,4], [2]
,因为第一组都在0
下取值f
,第二组都取值1
,依此类推...
类似这样的作品:
return [[x for x in lst if f(x) == val] for val in set(map(f,lst))]
,
但是,这似乎不是最佳选择(也不是pythonic的),因为内部循环不必要地扫描了整个列表,并多次计算了相同的f值。
我正在寻找一种解决方案,可以为每个元素理想地一次计算f
的值...
答案 0 :(得分:3)
如果您不是非理性地设置;-),则很简单:
from collections import defaultdict
lst = [0,1,2,3,4]
f = lambda x: x % 3
d = defaultdict(list)
for x in lst:
d[f(x)].append(x)
print(list(d.values()))
显示您想要的内容。 f()
被执行len(lst)
次,不能被击败
编辑:或者,如果必须的话:
from itertools import groupby
print([[pair[1] for pair in grp]
for ignore, grp in
groupby(sorted((f(x), x) for x in lst),
key=lambda pair: pair[0])])
这不要求f()
产生可用作dict键的值,但是会产生排序的额外费用,并且几乎是难以理解的。清晰性远胜于单行代码。
答案 1 :(得分:0)
@蒂姆·彼得斯(Tim Peters)是对的,这里是提到的setdefault
和另一个itertool.groupby
选项。
给出
import itertools as it
iterable = range(5)
keyfunc = lambda x: x % 3
代码
d = {}
for x in iterable:
d.setdefault(keyfunc(x), []).append(x)
list(d.values())
[list(g) for _, g in it.groupby(sorted(iterable, key=keyfunc), key=keyfunc)]