Pythonic方法在给定谓词为真的元素之后拆分列表

时间:2014-03-25 08:43:15

标签: python list

假设您有一个任意元素列表,如

['monkey', 'deer', 'lion', 'giraffe', 'lion', 'eagle', 'lion', 'fish']

应该在给定谓词的每个元素之后分成子列表,例如,

is_lion(element)

返回True。上面的例子应该成为

[['monkey', 'deer', 'lion'], ['giraffe', 'lion'], ['eagle', 'lion'], ['fish']]

有没有pythonic方式吗?

6 个答案:

答案 0 :(得分:5)

最简单的方法可能是:

out = [[]]
for element in lst:
    out[-1].append(element)
    if predicate(element):
        out.append([])

请注意,这会在最后out的{​​{1}},if predicate(element):末尾留下一个空列表。您可以通过添加以下内容来删除它:

element

答案 1 :(得分:2)

仅仅因为我们可以,一个功能性的单行:

from functools import reduce

reduce(lambda out, x: out[:-1] + [out[-1] + [x]] if not predicate(x) else out + [[x]], x, [[]])

答案 2 :(得分:1)

我更喜欢这个解决方案:

def f(outs, x):
    if outs[-1][-1:] == ["lion"]:
        outs.append([])
    outs[-1].append(x)
    return outs

def splitAfterLion(xs):
    return reduce(f,xs,[[]])

它可能不是非常pythonic,更实用。但它很简短,并且不会因结果中的空列表而受到影响。

答案 3 :(得分:0)

>>> import itertools
>>> l = ['monkey', 'deer', 'lion', 'giraffe', 'lion', 'eagle', 'lion', 'fish']
>>> f = lambda i: i == "lion"
>>> a = [list(j) for i, j in itertools.groupby(l, f)]
>>> a
[['monkey', 'deer'], ['lion'], ['giraffe'], ['lion'], ['eagle'], ['lion'], ['fish']]
>>> [i+j for i, j in zip(a[::2], a[1::2])]
[['monkey', 'deer', 'lion'], ['giraffe', 'lion'], ['eagle', 'lion']]

编辑:

>>> [i+j for i, j in itertools.zip_longest(a[::2], a[1::2], fillvalue=[])]
[['monkey', 'deer', 'lion'], ['giraffe', 'lion'], ['eagle', 'lion'], ['fish']]

答案 4 :(得分:0)

通过不使用itertool获取索引的另一种方法,请告诉我这是否适合您:

#!/usr/bin/python

ls = ['monkey', 'deer', 'lion', 'giraffe', 'lion', 'eagle', 'lion', 'fish', 'fish']

def is_lion(elm):
    return elm in ls

def mark_it(nm):
    ind = [ x+1 for x,y in enumerate(ls) if y == nm ]
    if ind[-1] < len(ls):
        ind.append(len(ls))
    return ind

def merge_it(ind):
    return [list(ls[x[0]:x[1]]) for x in zip(ind[::], ind[1::])]

name = 'lion'
if is_lion(name):
    index = [0]
    index.extend(mark_it(name))
    print merge_it(index)
else:
    print 'not found'

输出:

[['monkey', 'deer', 'lion'], ['giraffe', 'lion'], ['eagle', 'lion'], ['fish', 'fish']]

答案 5 :(得分:0)

这是一个解决方案:

def is_lion(a, element):
    start = 0
    for key,value in enumerate(a):
        if value == element:
            yield a[start:key+1]
            start = key+1

    # print out the last sub-list
    if value != 'lion':
        yield a[start:key+1]


a = ['monkey', 'deer', 'lion', 'giraffe', 'lion', 'eagle', 'lion', 'fish']

print [x for x in is_lion(a, 'lion')]