Python itertools groupby

2024-10-03 09:12:12 发布

您现在位置:Python中文网/ 问答频道 /正文

比方说,我有下面的元组列表

[('FRG', 'MCO TPA PIE SRQ', 'WAVEY EMJAY J174 SWL CEBEE '), 
('                    ', 'FMY RSW APF', 'WETRO DIW AR22 JORAY HILEY4'),
('                    ', 'FMY RSW APF', 'WETRO DIW AR22 JORAY HILEY4')
('FRG2', 'MCO TPA PIE SRQ', 'WAVEY EMJAY J174 SWL CEBEE '), 
('                    ', 'FMY RSW APF', 'WETRO DIW AR22 JORAY HILEY4')]

我该如何将这些数据分组,以便在最后进行一次dict,例如:

^{pr2}$

也就是说,我想把tuple[0]是一个单词的部分与tuple[0]为空(仅包含空白)的(可能很多)以下部分粘在一起。
我正在试验groupby和{},但还没有找到任何有效的解决方案。理想情况下,解决方案包含其中之一(即为了学习目的)。在


Tags: piemcotpafmysrqapfwetrojoray
3条回答

使用collections.defaultdict子类的解决方案:

l = [('FRG', 'MCO TPA PIE SRQ', 'WAVEY EMJAY J174 SWL CEBEE '),
('                    ', 'FMY RSW APF', 'WETRO DIW AR22 JORAY HILEY4'),
('                    ', 'FMY RSW APF', 'WETRO DIW AR22 JORAY HILEY4'),
('FRG2', 'MCO TPA PIE SRQ', 'WAVEY EMJAY J174 SWL CEBEE '),
('                    ', 'FMY RSW APF', 'WETRO DIW AR22 JORAY HILEY4')]

d = collections.defaultdict(list)
k = ''
for t in l:
    if t[0].strip():  # if the 1st value of a tuple is not empty
        k = t[0]      # capturing dict key
    if k:
        d[k].append(t[1])
        d[k].append(t[2])

print(dict(d))

输出:

^{pr2}$

我并不推荐它,但是要使用itertools.groupby()来实现这一点,您需要一个能记住上次使用的键的键函数。像这样:

def keyfunc(item, keys=[None]):
    if item[0] != keys[-1] and not item[0].startswith(" "):
        keys.append(item[0])        
    return keys[-1] 

d = {k: [y for x in g for y in x[1:]] for k, g in groupby(lst, key=keyfunc)}

一个简单的for循环看起来更干净,不需要任何imports:

^{pr2}$

函数groupbytakewhile不适合这类问题。在

groupby

基于key函数的^{}组。这意味着您需要保留最后遇到的第一个非空白元组元素才能使其正常工作。这意味着你要保持一些全球性的状态。通过保持这种状态,函数被称为"unpure",而大多数(甚至所有)itertools都是纯函数。在

from itertools import groupby, chain

d = [('FRG',                  'MCO TPA PIE SRQ', 'WAVEY EMJAY J174 SWL CEBEE '), 
     ('                    ', 'FMY RSW APF',     'WETRO DIW AR22 JORAY HILEY4'),
     ('                    ', 'FMY RSW APF',     'WETRO DIW AR22 JORAY HILEY4'),
     ('FRG2',                 'MCO TPA PIE SRQ', 'WAVEY EMJAY J174 SWL CEBEE '), 
     ('                    ', 'FMY RSW APF',     'WETRO DIW AR22 JORAY HILEY4')]

def keyfunc(item):
    first = item[0]
    if first.strip():
        keyfunc.state = first
    return keyfunc.state

{k: [item for idx, item in enumerate(chain.from_iterable(grp)) if idx%3 != 0] for k, grp in groupby(d, keyfunc)}

takewhile

^{}需要向前看,以确定何时停止yield值。这意味着它将自动从迭代器中弹出一个值,而不是实际用于每个组的值。要实际应用它,您需要记住最后一个位置,然后每次创建一个新的迭代器。它也有一个问题,你需要保持某种状态,因为你想取一个不带空格的元素,然后是那些只有空格的第一个元素。在

一种方法可能看起来像这样(但感觉不必要地复杂):

^{pr2}$

替代方案

您可以简单地创建自己的生成器,使之非常简单。它是takewhile方法的变体,但它不需要外部状态、islicetakewhilegroupby或跟踪索引:

^{3}$

相关问题 更多 >