在二进制列表中查找重复 0 的位置

问题描述

我有一个从 ak 返回的二进制列表表示 k = 2 的分类,我正在尝试 1) 识别 0,... 给定长度的子串的数量 - 至少说长度为 3 和 2) 标识这些子列表的开始和结束位置,因此在列表:L = [1,1,0] 中,理想情况下输出将是:number = 2start_end_locations = [[2,6],[13,15]]。 我正在使用的列表有数万个元素,因此我需要找到一种计算速度快的方法来执行此操作。我在 groupby 中看到了许多使用 itertools 的帖子,但我找不到将它们应用于我的任务的方法。 预先感谢您的建议!

解决方法

预先感谢您的建议!

  • 制作与您的模式匹配的 regular expression三个或多个零
  • 连接列表项为字符串
  • 使用 re.finditer 和匹配对象的 start() 和 end() 方法构建索引列表

将列表连接到一个字符串可能是最昂贵的部分 - 除非您尝试,否则您不会知道; finder 应该很快。需要多次通过数据,但可能工作量编码。


这可能会更好 - 单次遍历列表,但您需要注意逻辑 - 更努力地编写代码。

  • 使用 enumerate
  • 遍历列表
  • 当您发现
    • 捕获它的索引和
    • 设置一个标志,表明您正在跟踪零
  • 当你找到一个一个
    • 如果您要跟踪零
      • 捕获索引
      • 如果连续零的长度符合您的标准捕获该零的开始和结束索引
    • 根据需要重置标志和中间变量

word 版本有点不同:

def g(a=a):
    y = []
    criteria = 3
    start,end = 0,0
    prev = 1
    for i,n in enumerate(a):
        if not n:        # n is zero
            end = i
            if prev:     # previous item one
                start = i
        else:
            if not prev and end - start + 1 >= criteria:
                y.append((start,end))
        prev = n
    return y
,

您可以使用 zip() 依次检测 1,0 和 0,1 中断的索引。然后在中断索引上使用 zip() 以形成范围并提取以零开头并跨越至少 3 个位置的范围。

cp: cannot copy a directory <path-to-the-test-folder-in-temp> into itself,<path-to-the-test-folder-in-temp/image/home/first>

输出:

def getZeroStreaks(L,minSize=3):
    breaks = [i for i,(a,b) in enumerate(zip(L,L[1:]),1) if a!=b]
    return [[s,e-1] for s,e in zip([0]+breaks,breaks+[len(L)])
                        if e-s>=minSize and not L[s]]

该函数可以泛化为查找列表中任何值的条纹:

L = [1,1,0]
print(getZeroStreaks(L))
[[2,6],[13,15]]

from timeit import timeit

t = timeit(lambda:getZeroStreaks(L*1000),number=100)/100

print(t) # 0.0018 sec for 16,000 elements

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...