基于不变/哈希的拆分/分区列表?

时间:2018-08-27 23:48:07

标签: python-3.x itertools

我有一个列表[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的值...

2 个答案:

答案 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

代码

setdefault

d = {}
for x in iterable:
    d.setdefault(keyfunc(x), []).append(x)

list(d.values())

groupby

[list(g) for _, g in it.groupby(sorted(iterable, key=keyfunc), key=keyfunc)]

另请参阅more on itertools.groupby