【问题标题】:How can I delete all zeros except for x of them in every run of consecutive zeros within a list?如何在列表中的每次连续零运行中删除除 x 之外的所有零?
【发布时间】:2012-07-28 18:33:53
【问题描述】:

对于 Python 列表中每次运行 x 或多个连续零,我想删除运行中的所有零,但 x 除外。如果x = 0,则删除所有零。

我在想一个 Python 函数,它接受一个列表 L 和一个数字 x 作为输入。

例如,让L = [7, 0, 12, 0, 0, 2, 0, 0, 0, 27, 10, 0, 0, 0, 0, 8]

  • 如果x = 0,则返回L = [7, 12, 2, 27, 10, 8]
  • 如果x = 1,则返回L = [7, 0, 12, 0, 2, 0, 27, 10, 0, 8]
  • 如果x = 2,则返回L = [7, 0, 12, 0, 0, 2, 0, 0, 27, 10, 0, 0, 8]
  • 如果x = 3,则返回L = [7, 0, 12, 0, 0, 2, 0, 0, 0, 27, 10, 0, 0, 0, 8]
  • 如果x = 4,则返回L = [7, 0, 12, 0, 0, 2, 0, 0, 0, 27, 10, 0, 0, 0, 0, 8](与原L相同)
  • 如果是 x >= 5,则返回原始 L,因为没有 5 个或更多连续零的运行。

任何帮助将不胜感激。

【问题讨论】:

  • 我不确定是否有一个简洁的衬里。您可能需要遍历列表,边走边计算零,并在找到多余的零时删除它们。
  • @Max,您可以将我的答案写在一行中。不过会超过 80 个字符 :)

标签: python list del


【解决方案1】:

作为生成器,这很容易做到。如果您想要一个删除零运行的新列表,请将您的调用包装在 list 构造函数中。

def compact_zero_runs(iterable, max_zeros):
    zeros = 0
    for i in iterable:
        if i == 0:
            zeros += 1
            if zeros <= max_zeros:
                yield i
        else:
            zeros = 0
            yield i

【讨论】:

  • 这个生成器比我想出的要好。 (+1)
  • @Blckknght,您介意验证我的理解是否正确吗?生成器函数采用可迭代检查的值来查看它们是否为 0。如果为零,则递增零并检查是否已达到 max_zeros。如果已达到 max_zeros,则在 iterable 中产生该值。否则重新开始 for 循环。如果 iterable 中的值不为零,则零计数保持 0 并在 iterable 中产生该值。要显示列表,请在主函数之外定义这个生成器,然后在原始函数(我正在处理的)中调用它(比如)?
  • @b_ron_,我认为您有两处稍有错误。首先,如果zeros 计数超过max_zeros,它不会产生值(这些是被丢弃的多余零)。它是在您超出限制之前产生的那些。另一点是,当你达到一个非零值时,它总是将零的计数重置为 0,忘记之前有多少(因为你只需要计算连续的零运行)。您从生成器获取列表的语法完全正确。
【解决方案2】:

使用 groupby:

def del_zeros(lst, n):
    lst = (list(j)[:n] if i else list(j) 
           for i,j in itertools.groupby(lst, key=lambda x:x==0))

    return [item for sublist in lst for item in sublist]

还有测试:

>>> [del_zeros(L, i) for i in range(5)]
[[7, 12, 2, 27, 10, 8],
 [7, 0, 12, 0, 2, 0, 27, 10, 0, 8],
 [7, 0, 12, 0, 0, 2, 0, 0, 27, 10, 0, 0, 8],
 [7, 0, 12, 0, 0, 2, 0, 0, 0, 27, 10, 0, 0, 0, 8],
 [7, 0, 12, 0, 0, 2, 0, 0, 0, 27, 10, 0, 0, 0, 0, 8]]

【讨论】:

    【解决方案3】:
    from itertools import groupby, chain, islice
    from functools import partial
    from operator import eq
    
    def f(L, x):
        groups = groupby(L, partial(eq, 0))
        return list(chain.from_iterable(islice(v, x) if k else v for k,v in groups))
    

    【讨论】:

      猜你喜欢
      • 2012-12-29
      • 1970-01-01
      • 2019-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-01
      • 2015-03-05
      • 2017-03-17
      相关资源
      最近更新 更多