计算列表中其他元素之间特定元素的数量

Count number of specific elements in between other elements in list

我正在读取数据文件。行以连续的数字(步数)开始,有时每行之间有一个 0.

例如:

1
0
2
0
3
4
5
0
0
0
6
0

我如何创建一个列表来计算每个步骤之间的 0 的数量。

我想要这样的列表:

finalList = [1,1,0,0,3,1]

表示每一步包含的0个数,即:第一步有1个零,第二步有1个零,第三步有0个零,第四步有0个零,第五步有3个零,第六步有1 个零。

如果您的数据文件看起来与您描述的完全一致(例如,除了增加步长和零的数量之外没有其他数字),以下代码应该可以工作。

cur = 0
res = []
with open("file.txt") as f:
    for line in f:
        if line.strip() == '0':
            cur += 1
        else:
            res.append(cur)
            cur = 0

我想到了这个:

finalList = []
count = 0
step = None

for e in [1, 0, 2, 0, 3, 4, 5, 0, 0, 0, 6, 0]:
   if e > 0:
      if step:
         finalList.append(count)
      step = e
      count = 0
   else:
      count += 1
if step:
    finalList.append(count)
a = [1,0,2,0,3,4,5,0,0,0,6,0]
finalList = []
count = 0
for i in xrange(len(a)):
    if i == 0 : continue
    if a[i] == 0 :
        count += 1
    else : 
        finalList.append(count)
        count = 0
finalList.append(count)

备选方案

# temp list (copy of l with last element if doesn't exist)
_l = l if l[-1] > 0 else l + [max(l) + 1]
# _l.index(i) - _l.index(i - 1) - 1 = distance between elements
[_l.index(i) - _l.index(i - 1) - 1 for i in range(2, max(_l) + 1)]

可能是使用 Python 附带电池的过于聪明的解决方案:

from itertools import chain, groupby

with open("file.txt") as f:
    # Add extra zeroes after non-zero values so we see a group when no padding exists
    extrazeroes = chain.from_iterable((x, 0) if x else (x,) for x in map(int, f))

    # Count elements in group and subtract 1 if not first group to account for padding
    # The filter condition means we drop non-zero values cheaply
    zerocounts = [sum(1 for _ in g) - bool(gnum) for gnum, (k, g) in enumerate(groupby(extrazeroes)) if k == 0]

    # If leading zeroes (before first non-zero line) can't happen, simplify to:
    zerocounts = [sum(1 for _ in g) - 1 for k, g in groupby(extrazeroes) if k == 0]

是的,它有点复杂(如果您不关心在两个非零值之间没有间隙的地方包含零,它会简单得多),但它很简洁并且应该非常快。如果您可以在计数中省略 0s,它会简化为更清晰:

with open("file.txt") as f:
    zerocounts = [sum(1 for _ in g) for k, g in groupby(map(int, f)) if k == 0]

郑重声明,如果符合要求,我会使用后者。前者可能不应该进入生产代码。 :-)

请注意,根据您的用例,使用 groupby 可能是解决更广泛问题的好主意;在评论中,您提到您正在将所有行存储在文件中(使用 f = f.readlines()),这意味着您将访问它们,可能基于存储在 zerocounts 中的值。如果您有一些特定需要根据后续零的数量处理每个 "step",则对上述代码进行改编可能会节省您通过惰性分组和处理来清理文件的内存开销。

注意: 为了避免将整个文件吞入内存,在 Python 2 中,您需要添加 from future_builtins import map 所以 map 是一个惰性生成器函数,就像它在 Py3 中一样,而不是加载整个文件并将其全部转换为 int 预先。如果您不想踩 map,导入并使用 itertools.imap 而不是 map 进行 int 转换可实现相同的目标。