计数器允许重复
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)
我想对相同状态的序列进行分组,以便学习红绿灯相位计时。
我尝试使用 collections
的 Counter
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)]
我有一个定义可能状态的红绿灯枚举:
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)
我想对相同状态的序列进行分组,以便学习红绿灯相位计时。
我尝试使用 collections
的 Counter
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)]