允许重复的计数器

时间:2018-05-04 14:11:38

标签: python python-3.x python-collections

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

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)

我想对相同状态的序列进行分组,以便了解交通灯阶段的时间。

我尝试使用Countercollections,如下所示:

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,              '绿色':30,              '黄色':9             })

2 个答案:

答案 0 :(得分:3)

我会使用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)]

答案 1 :(得分:0)

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)]