计数器允许重复

Counter allowing repetitions

我有一个定义可能状态的红绿灯枚举:

class TrafficLightPhase(Enum):
    RED = "RED"
    YELLOW = "YELLOW"
    GREEN = "GREEN"

我每秒轮询一个交通灯以获取当前状态,然后使用此函数将值放入 deque 中:

def read_phases():
    while running:
        current_phase = get_current_phase_phases()
        last_phases.append(current_phase)
        time.sleep(1)

我想对相同状态的序列进行分组,以便学习红绿灯相位计时。

我尝试使用 collectionsCounter class,像这样:

counter = collections.Counter(last_phases)

它很好地分组了不同的状态,但我无法知道下一个周期何时开始。 是否有类似于 Counter 的允许重复的数据结构? 这样我可以获得如下结果:

Counter({
         'RED': 10,
         'GREEN': 10, 
         'YELLOW': 3,
         'RED': 10,
         'GREEN': 10, 
         'YELLOW': 3,
         'RED': 10,
         'GREEN': 10, 
         'YELLOW': 3
        })

而不是: 柜台({ 'RED': 30, 'GREEN': 30, 'YELLOW': 9 })

我会为此使用 itertools.groupby。它会将同一元素的连续 运行 分组,然后您可以检查每个 运行.

的长度
>>> from itertools import groupby
>>> last_phases= ['red', 'red', 'yellow', 'red', 'red', 'green']
>>> [(key, len(list(group))) for key,group in groupby(last_phases)]
[('red', 2), ('yellow', 1), ('red', 2), ('green', 1)]

collections.Counter 在这里不起作用,因为它不按顺序区分项目。

我推荐你使用itertools.groupby

但是,作为参考,下面是使用 collections.defaultdict 的解决方案。

from collections import defaultdict
from itertools import islice, chain, zip_longest

d = defaultdict(lambda: defaultdict(int))

last_phases= ['red', 'red', 'yellow', 'red', 'red', 'green']

c = 0
for i, j in zip_longest(last_phases, islice(last_phases, 1, None)):
    d[c][i] += 1
    if i != j:
        c += 1

res = list(chain.from_iterable(i.items() for i in d.values()))

[('red', 2), ('yellow', 1), ('red', 2), ('green', 1)]