【问题标题】:What's the most Pythonic way to identify consecutive duplicates in a list?识别列表中连续重复项的最 Pythonic 方法是什么?
【发布时间】:2011-09-15 04:42:55
【问题描述】:

我有一个整数列表,我希望能够识别连续的重复块:也就是说,我想生成一个保持顺序的重复列表,其中每个重复包含(int_in_question,出现次数)。

例如,如果我有一个类似的列表:

[0, 0, 0, 3, 3, 2, 5, 2, 6, 6]

我希望结果是:

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

我有一个相当简单的方法,使用 for 循环、临时和计数器:

result_list = []
current = source_list[0]
count = 0
for value in source_list:
    if value == current:
        count += 1
    else:
        result_list.append((current, count))
        current = value
        count = 1
result_list.append((current, count))

但我真的很喜欢 python 的函数式编程习惯,我希望能够用一个简单的生成器表达式来做到这一点。但是,我发现在使用生成器时很难保持子计数。我觉得两步过程可能会让我到达那里,但现在我被难住了。

有没有一种特别优雅/pythonic 的方式来做到这一点,尤其是使用生成器?

【问题讨论】:

标签: list duplicates generator python


【解决方案1】:
>>> from itertools import groupby
>>> L = [0, 0, 0, 3, 3, 2, 5, 2, 6, 6]
>>> grouped_L = [(k, sum(1 for i in g)) for k,g in groupby(L)]
>>> # Or (k, len(list(g))), but that creates an intermediate list
>>> grouped_L
[(0, 3), (3, 2), (2, 1), (5, 1), (2, 1), (6, 2)]

Batteries included,正如他们所说。

使用来自 JBernardo 的 sum 和生成器表达式的建议;见评论。

【讨论】:

  • +1,也许您可​​以将len(list(g)) 更改为sum(1 for i in g) 以避免中间存储。
  • @JBernardo:很好的建议,谢谢。当我为此使用groupby 时,从g 创建一个列表总是让我感到困扰。
  • @JBernardo:实际上我要创建中间列表。虽然也许做总和会更有效,但我认为前者更具可读性(确实准确地说明了我们想要发生的事情),因此更pythonic!我确实认为这种“添加”解决方案暗示了生成器中缺少的东西,特别是没有办法明确地通过内置函数告诉将生成多少个元素。将来可能会修改吗?
  • @machine:原则上是不可能的。考虑一下:def long_gen(): while True: yield 1 这个len 是什么?见:stackoverflow.com/questions/390852/…
  • @machine:不客气。我在其他地方看到过sum 的这种用法,但没想到在这种情况下使用它。我想大多数读者都会很快理解它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-21
  • 1970-01-01
  • 2017-05-01
相关资源
最近更新 更多