我经常遇到需要将一个序列分割成满足和不满足给定谓词(保留原始相对排序)的元素的两个子序列。如何根据谓词分割一个序列?
这个假设的“分流”功能会看在行动中是这样的:
>>> data = map(str, range(14))
>>> pred = lambda i: int(i) % 3 == 2
>>> splitter(data, pred)
[('2', '5', '8', '11'), ('0', '1', '3', '4', '6', '7', '9', '10', '12', '13')]
我的问题是:
没有的Python已经有一个标准的/内置的方式做到这一点?
这个功能当然不难编码(见下面的附录),但由于多种原因,我宁愿使用标准/内置方法而不是自卷方法。
谢谢!
附录:
迄今在Python处理这个任务,我已经找到了最好的标准功能是itertools.groupby
。将它用于然而这个特殊的任务,有必要调用两次谓词函数为每个列表成员,这是我找到烦人傻:
>>> import itertools as it
>>> [tuple(v[1]) for v in it.groupby(sorted(data, key=pred), key=pred)]
[('0', '1', '3', '4', '6', '7', '9', '10', '12', '13'), ('2', '5', '8', '11')]
(最后输出上述从先前在该示出的期望的一个不同满足谓词元素的子说到最后,而不是第一个,但这是非常轻微的,而且很容易,如果需要修理。)
人能避免谓词冗余呼叫(这样做,基本上是一个“内联memoization“),但我最好的刺这个得到相当详细,与splitter(data, pred)
的简单相差甚远:
>>> first = lambda t: t[0]
>>> [zip(*i[1])[1] for i in it.groupby(sorted(((pred(x), x) for x in data),
... key=first), key=first)]
[('0', '1', '3', '4', '6', '7', '9', '10', '12', '13'), ('2', '5', '8', '11')]
顺便说一句,如果你不关心保留原来的排序,的sorted
默认的排序顺序能够完成任务(所以key
参数可以从sorted
调用可以省略):
>>> [zip(*i[1])[1] for i in it.groupby(sorted(((pred(x), x) for x in data)),
... key=first)]
[('0', '1', '3', '4', '6', '7', '9', '10', '12', '13'), ('2', '5', '8', '11')]
可以帮助我们理解为什么你不想写一个函数? – 2012-01-09 19:31:42
可能重复的[Python:拆分基于条件的列表?](http://stackoverflow.com/questions/949098/python-split-a-list-based-on-a-condition) – user 2014-09-21 03:03:47