数字 1 和 0 的数据检测器

Data detector for number 1 and 0

我有一个仅包含 0 和 1 的数据集。我想要一个检测器来查找 1 的起始位置和 1 的结束位置,然后 return 将与它们的索引相关的内容分别放入不同的列表.所以我写了一些代码如下:

n= [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
    1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1]

def detector (data):
    x = 0
    start = []
    end = []
    for index, i in enumerate(data):
        if x == 0 and i == 1: 
            start.append((index+1))
            x == 1
        elif x == 1 and i==0:
                end.append((index))
                x == 0
    return start, end

print (detector(n))

然而,当我 运行 上面的代码时,它 return 如下所示,这不是我想要的输出。

([1, 2, 3, 4, 22, 23, 24, 25, 26, 27, 28, 34, 35, 36, 37, 38], [])

我想要的输出如下:

([1, 22, 34], [4,28,38])

正如您在上面看到的,start_time 应该是 [1,22,34] 而 end_time 应该是 [4,28,38]。

如果有人知道如何解决这个问题,请告诉我。赞赏!!

一个问题当然是,您不更改标志。 == 是比较运算符,不会为 flag

赋新值

您也可以尝试使用 groupby:

import itertools
L = [[y[0] for y in it] 
     for x,it in
     itertools.groupby(enumerate(n),lambda x: x[1])
     ][::2]
res = [x[0] for x in L],[x[-1] for x in L]

如果不使用索引,您可能会得出更正确的解决方案。

感谢vishes_shell指正

n = [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
     1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1]

prev_num = 0

starts = []
ends = []
result = (starts, ends)

for idx, num in enumerate(n):
    if prev_num == 0 and num == 1:
        starts.append(idx + 1)
    elif prev_num == 1 and num == 0:
        ends.append(idx + 1)
    elif num == 1 and idx == (len(n) - 1):
        ends.append(idx + 1)
    prev_num = num

print(result)

打印:

[[1, 22, 34], [5, 29, 38]]

使用 enumerate to get positions of 1s and zip 查找连续 1 的序列 starts/ends

ones_positions = [position
                  for position, value in enumerate(n)
                  if value == 1]
ones_starts = [ones_positions[0]] + [
    next_position
    for position, next_position in zip(ones_positions,
                                       ones_positions[1:])
    if next_position - position > 1]
ones_ends = [position
             for position, next_position in zip(ones_positions,
                                                ones_positions[1:])
             if next_position - position > 1] + [ones_positions[-1]]

给我们

>>>ones_starts
[0, 21, 33]
>>>ones_ends
[3, 27, 37]

如果您希望索引从 1 开始(当它们自然从 0 开始时)[=26],我们可以指定 enumeratestart 参数=]

ones_positions = [position
                  for position, value in enumerate(n, start=1)
                  if value == 1]

之后

>>>ones_starts
[1, 22, 34]
>>>ones_ends
[4, 28, 38]

最后我们可以把它写成函数:

def detector(data, target_value=1):
    positions = [position
                 for position, value in enumerate(data, start=1)
                 if value == target_value]
    start_times = [positions[0]] + [
        next_position
        for position, next_position in zip(positions,
                                           positions[1:])
        if next_position - position > 1]
    end_times = [position
                 for position, next_position in zip(positions,
                                                    positions[1:])
                 if next_position - position > 1] + [positions[-1]]
    return start_times, end_times

并测试

n = [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
     1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
print(detector(n))

给我们

([1, 22, 34], [4, 28, 38])

因为@DanielChristiany 指出了您的错误所在。我将向您展示我的解决方案,它比任何展示的解决方案都快(至少可以正常工作):

edges = (index for index, i in enumerate(n[1:], 1) if i != n[index-1])
if n[0] == 1:
    edges = (1, *edges)
if n[-1] == 1:
    some = (*edges, len(n))
print(edges[::2], edges[1::2])

基本上它首先搜索元素从0变为1或从1变为0的边。然后检查第一个和最后一个元素是否为1,然后打印结果。

此解决方案还使用了较少的内存,因为它使用了生成器。