按连续的公共元素拆分列表

Split the list by consecutive common element

我有以下列表,其中仅包含两个字符 'N' 和 'C'

ls = ['N', 'N', 'N', 'C', 'C', 'C', 'C', 'N', 'C', 'C']

我想做的是提取列表中连续的"C"和return索引。

产生类似

的东西
  chunk1 = [('C', 'C', 'C', 'C'), [3,4,5,6]]
  chunk2 = [('C', 'C'), [8,9]]

  # and when there's no C it returns empty list.

如何在 Python 中实现?

我试过了,但没有如我所愿:

from itertools import groupby
from operator import itemgetter
tmp = (list(g) for k, g in groupby(enumerate(ls), itemgetter(1)) if k == 'C')
zip(*tmp)

移动zip(*...)里面的列表推导:

import itertools as IT
import operator

ls = ['N', 'N', 'N', 'C', 'C', 'C', 'C', 'N', 'C', 'C']

[list(zip(*g))[::-1] 
 for k, g in IT.groupby(enumerate(ls), operator.itemgetter(1)) 
 if k == 'C']

产量

[[('C', 'C', 'C', 'C'), (3, 4, 5, 6)], [('C', 'C'), (8, 9)]]

在Python2中,list(zip(...))可以用zip(...)代替,但是由于在Python3zipreturns中有一个迭代器,所以我们需要 list(zip(...))。要使解决方案与 Python2 和 Python3 兼容,请在此处使用 list(zip(...))

ls = ['N', 'N', 'N', 'C', 'C', 'C', 'C', 'N', 'C', 'C']

def whereMyCharsAt(haystack, needle):
    start = None
    for ii, char in enumerate(haystack):
        if char == needle:
            if start is None:
                start = ii
        else:
            if start is not None:
                yield [needle] * (ii - start), range(start, ii)
                start = None

    if start is not None:
        yield [needle] * (len(haystack) - start), range(start, len(haystack))

for indexes in whereMyCharsAt(ls, 'C'):
    print indexes

这会打印:

(['C', 'C', 'C', 'C'], [3, 4, 5, 6])
(['C', 'C'], [8, 9])

使用生成器函数。您需要做的就是在解压缩组时反转group。 所以使用 yield zip(*group)[::-1]

from itertools import groupby
from operator import itemgetter
def solve(ls):
    for key, group in groupby(enumerate(ls), itemgetter(1)):
        if key =='C':
            yield zip(*group)[::-1]

ls =  ['N', 'N', 'N', 'C', 'C', 'C', 'C', 'N', 'C', 'C']
print list(solve(ls))


[[('C', 'C', 'C', 'C'), (3, 4, 5, 6)], [('C', 'C'), (8, 9)]]