我經常遇到需要將一個序列分割成滿足和不滿足給定謂詞(保留原始相對排序)的元素的兩個子序列。如何根據謂詞分割一個序列?
這個假設的「分流」功能會看在行動中是這樣的:
>>> 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