关于列表:Python itertools groupby没有像我期望的那样分组

Python itertools groupby not grouping as I expect

假设我有一根这样的绳子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
st='''Line 1
Line 2
Line 3
Line 4

Line 5
Line 6

Line 7
Line 8
Line 9

Line 10
Line 11
Line 12
Line 13
Line 14'''

# may be really big...

现在假设我想要一个由空白行分组的LOL:

1
2
3
4
[['Line 1', 'Line 2', 'Line 3', 'Line 4'],
 ['Line 5', 'Line 6'],
 ['Line 7', 'Line 8 ', 'Line 9'],
 ['Line 10', 'Line 11', 'Line 12', 'Line 13', 'Line 14']]

我知道我可以用regex拆分创建LOL:

1
2
[[x] for x in re.split(r'^\s*
'
,st,flags=re.MULTILINE)]

但是,我尝试用一个非regex python生成器来创建它。我最近得到的是这件可怕的事情(包括空白处,我知道这一点都不有效…):

1
2
3
4
5
result=[]        
for sub in (group for key, group in itertools.groupby(st.splitlines(), lambda x: not x.rstrip())):
    result.append(list(sub))

print result

有什么关于前进方向的提示吗?

我有点回避这个问题。


我可能会写

1
2
3
4
>>> grouped = itertools.groupby(map(str.strip, st.splitlines()), bool)
>>> [list(g) for k,g in grouped if k]
[['Line 1', 'Line 2', 'Line 3', 'Line 4'], ['Line 5', 'Line 6'],
['Line 7', 'Line 8', 'Line 9'], ['Line 10', 'Line 11', 'Line 12', 'Line 13', 'Line 14']]

这也将处理空白行,而基于

的拆分不会处理空白行。另一方面,它不保留前导和尾随空白,这是您可能需要的'Line 8 '示例中的空白。如果这很重要,你可以:

1
grouped = itertools.groupby(st.splitlines(), lambda x: bool(x.strip()))

(看着它,它非常接近你已经在做的事情。)


有什么理由不适合你吗?

1
2
3
4
5
6
7
8
9
>>> lol = [group.split("
"
) for group in st.split("

"
)]
>>> pprint(lol)
[['Line 1', 'Line 2', 'Line 3', 'Line 4'],
 ['Line 5', 'Line 6'],
 ['Line 7', 'Line 8 ', 'Line 9'],
 ['Line 10', 'Line 11', 'Line 12', 'Line 13', 'Line 14']]