查找列表中的所有子序列

Find all subsequences in list

我有一个 1 和 0 的列表如下:

lst = [1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1]

我正在寻找一种方法来找到 所有 此列表中的 0 序列和 returns 它们的索引,即:

[1, 3]
[8, 9]
[13, 13]
[15, 16]

显示了一种获取最长序列的方法,但我想不出一种方法来从中获取所有序列。

list = [1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1]

indexes_counts = []
start_zero_index = -1
is_inside_zero_sequence = False
zero_length = 0
# Use enumerate to loop on the lists and indexes
for i, x in enumerate(list):
    # If inside a zeroes sequence
    if is_inside_zero_sequence:
        # If current item is zero too
        if 0 == x:
            # Increase the zro_length counter
            zero_length += 1
        # Else, current element is not zero
        else:             
            # Handle end of zeroes sequence
            indexes_counts.append([start_zero_index, zero_length])
            is_inside_zero_sequence = False
            zero_length = 0
    # If not in zeroes sequence and current number is not zero
    elif 0 == x:
            # Handle not zero
            is_inside_zero_sequence = True
            start_zero_index = i
            zero_length = 1

# [[1, 3], [8, 2], [13, 1], [15, 2]]
print(indexes_counts)
def f(l):
    _1to0 = [ i+1 for i, (x, y) in enumerate(zip(l[:-1], l[1:])) if y == 0 and x != y ]
    _0to1 = [ i for i, (x, y) in enumerate(zip(l[:-1], l[1:])) if x == 0 and x != y ]
    if l[0] == 0:
      _1to0.insert(0,0)
    if l[-1] == 0:
      _0to1.append(len(l))
    return zip(_1to0, _0to1)
  1. 检测变化 1 -> 0(开始)和 0 -> 1(结束)

  2. 如果从 0 开始,在索引 0 添加一个开始

  3. 如果以0结尾,则在最后一个索引处添加一个结尾

  4. 组合开始和结束成对

    In [1]: list(f([1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1]))
    Out[1]: [(1, 3), (8, 9), (13, 13), (15, 16)]

对于 Python 3.8,您可以使用 Walrus operator

修改参考代码中的第一个答案

代码

from itertools import groupby
import operator

lst = [1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1]

r = [(p[1][0][0], p[1][-1][0]) for (x,y) in groupby(enumerate(lst), operator.itemgetter(1)) if (p := (x, list(y)))[0] == 0]
print(r)

输出

[(1, 3), (8, 9), (13, 13), (15, 16)]

说明

将 Walrus 运算符添加到 OP 代码参考我们有:

r = [p for (x,y) in groupby(enumerate(lst), operator.itemgetter(1)) if (p := (x, list(y)))[0] == 0]
# Outputs: [(0, [(1, 0), (2, 0), (3, 0)]), (0, [(8, 0), (9, 0)]), (0, [(13, 0)]), (0, [(15, 0), (16, 0)])]

列表理解中的条件:

(p := (x, list(y)))[0] # is a check for x == 0 

需要在 p

中捕获正确的术语

例如第一个 p[1] 是:

[(1, 0), (2, 0), (3, 0)]   

我们想要 (1, 3) 列表的第一项和最后一项的索引为 0

p[1][0][0]   # index zero of first tuple -> 1
p[1][-1][0]  # index zero of last tuple  -> 3

所以一般来说我们有元组:

(p[1][0][0], p[1][-1][0])