Счетчик разрешающих повторений - PullRequest
0 голосов
/ 04 мая 2018

У меня есть светофор Enum, определяющий возможные состояния:

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)

Я хочу сгруппировать последовательности одного и того же состояния, чтобы узнать временные характеристики фаз светофора.

Я пытался использовать Counter класс collections, например:

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

вместо: Счетчик ({ «КРАСНЫЙ»: 30, «ЗЕЛЕНЫЙ»: 30, «ЖЕЛТЫЙ»: 9 })

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

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)]
0 голосов
/ 04 мая 2018

Я бы использовал 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)]
...