【问题标题】:Grouping a list of sublists by some of the values in each sublist按每个子列表中的某些值对子列表列表进行分组
【发布时间】:2017-02-18 01:36:25
【问题描述】:

我有一本包含列表的字典。例如,

{1: [[sender11, receiver11, text11, address11]], 
 2: [[sender21, receiver21, text21, address21], [sender22, receiver22, text22, address22]], 
 3: [[sender31, receiver31, text31, address31], [sender32, receiver32, text32, address32], [sender33, receiver33, text33, address33]]
 4: [[sender41, receiver41, text41, address41], [sender42, receiver42, text42, address42], [sender43, receiver43, text43, address43], [sender44, receiver44, text44, address44]]}

我想要做的是,对于包含具有 2 个或更多元素的列表的字典元素(即本例中的 dict[2]dict[3]dict[4]),我对 sender, receiver, text 进行比较每个列表值。对于每组具有相同sender, receiver, text 的列表值,我会做一些事情。

例如,在dict[3] 中,如果sender31, receiver31, text31sender32, receiver32, text32sender33, receiver33, text33 的值相同,那么我将对所有3 个列表值进行处理。

dict[4] 中说,如果sender41, receiver41, text41sender42, receiver42, text42 的值相同,而sender43, receiver43, text43sender44, receiver44, text44 的值相同,但与sender41, receiver41, text41 不同,那么我将处理这两个单独分组。

我编写了一个 Python 脚本,它几乎可以蛮力比较 sender21, receiver21, text21sender22, receiver22, text22 的值,即

if sender21 == sender22 and receiver21 == receiver22 and text21 == text22:
   # Do something

这效率不高,因为它只适用于 2 个列表值,但我不知道我应该如何实现它以便它适用于任何数量大于 1 的列表值。

【问题讨论】:

    标签: python python-2.7 list dictionary comparison


    【解决方案1】:

    我认为defaultdict 是显而易见的方式:

    from collections import defaultdict
    
    def collate(seq):
        groups = defaultdict(list)
        for subseq in seq:
            groups[tuple(subseq[:3])].append(subseq[3])
        return groups
    

    根据您的实际数据,您可以将上述函数中的tuple(subseq[:3]) 替换为例如(subseq[1], subseq[4], subseq[5]),或附加的 subseq[3]subseq 本身...这取决于您对数据的处理方式。

    但是,键必须是元组而不是列表,因为键必须是不可变的。

    例子:

    >>> data = [
    ...     ['S1', 'R1', 'T1', 'A3'],
    ...     ['S2', 'R2', 'T2', 'A4'],
    ...     ['S1', 'R1', 'T1', 'A5'],
    ...     ['S2', 'R2', 'T2', 'A6']
    ... ]
    

    >>> collate(data)
    defaultdict(<type 'list'>, {
        ('S2', 'R2', 'T2'): ['A4', 'A6'],
        ('S1', 'R1', 'T1'): ['A3', 'A5']
    })
    

    您可以像使用任何其他字典一样使用它,例如

    >>> for (sender, receiver, text), addresses in collate(data).items():
    ...     print sender, receiver, text
    ...     print '|'.join(addresses)
    ...     print
    ... 
    S2 R2 T2
    A4|A6
    
    S1 R1 T1
    A3|A5
     
    

    【讨论】:

    • 谢谢!这很好用。但是,如果现在不是完全匹配(sender, receiver, text),而是希望(sender, receiver, text)(receiver, sender, text) 在同一个组中,即发送者/接收者的顺序无关紧要,该怎么办?这可能吗?我需要散列吗?
    • a) 不可变和 b) 不关心顺序的集合类型是 frozenset,所以像 groups[frozenset(subseq[:2]), subseq[2]].append(subseq[3]) 这样的东西听起来很正确 - 必要时进行调整。
    • 顺便说一句,这是您应该知道或能够从文档中快速找到的东西,以便成为一名有效的程序员。一遍又一遍地阅读docs.python.org/2/library/stdtypes.html,直到您知道从长远来看,标准类型将大大回报您的努力。
    猜你喜欢
    • 2021-07-11
    • 1970-01-01
    • 2010-11-07
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    • 2019-11-06
    • 2016-03-20
    • 1970-01-01
    相关资源
    最近更新 更多