(抽象的)问题是这样的:我有一个日志文件
A: 1
A: 2
A: 3
B: 4
B: 5
A: 6
C: 7
D: 8
A: 9
A: 10
A: 11
我想以这样的列表结尾:
[["1", "2", "3"], ["6"], ["9", "10", "11"]]
其中文件已分解为以开头的字符串“运行” A
。我知道可以用它itertools.groupby
来解决这个问题,现在我有了这个解决方案(f
文件中各行的列表)。
starts_with_a = lambda x: x.startswith("A")
coalesced = [g for _, g in groupby(f), key=starts_with_a]
runs = [re.sub(r'A: ', '', s) for s in coalesced if starts_with_a(s)]
因此,我使用了groupby,但是随后我必须过滤掉不以“ A”开头的内容。没关系,而且很简洁,但是有没有更优雅的方法呢?我喜欢这样一种方式:
帮我驾驭itertools
!
是的,过滤掉不是以开头的行,A
而是使用为返回的每个组生成的键groupby()
。它是key
函数的返回值,因此True
适用于以开头的行A
。我将str.partition()
在这里使用而不是正则表达式:
coalesce = (g for key, g in groupby(f, key=lambda x: x[:1] == "A") if key)
runs = [[res.partition(':')[-1].strip() for res in group] for group in coalesce]
由于您的str.startswith()
参数是固定宽度的字符串文字,因此您也可以使用切片。x[:1]
将第一个字符切成薄片并与之进行比较'A'
,这使您与进行相同的测试x.startswith('A')
。
我使用生成器表达式对groupby()
过滤进行分组;您可以将其内联到一个列表理解中:
runs = [[res.partition(':')[-1].strip() for res in group]
for key, group in groupby(f, key=lambda x: x[:1] == "A") if key]
演示:
>>> from itertools import groupby
>>> f = '''\
... A: 1
... A: 2
... A: 3
... B: 4
... B: 5
... A: 6
... C: 7
... D: 8
... A: 9
... A: 10
... A: 11
... '''.splitlines(True)
>>> coalesce = (g for key, g in groupby(f, key=lambda x: x[:1] == "A") if key)
>>> [[res.partition(':')[-1].strip() for res in group] for group in coalesce]
[['1', '2', '3'], ['6'], ['9', '10', '11']]
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句