【问题标题】:Group Python lists based on repeated items根据重复项对 Python 列表进行分组
【发布时间】:2015-08-17 19:01:37
【问题描述】:

这道题和Group Python list of lists into groups based on overlapping items这道题很像,其实可以说是重复题了。

基本上,我有一个子列表列表,其中每个子列表包含一些整数(这个数字在子列表中不一样)。我需要对共享一个或多个整数的所有子列表进行分组。

我提出一个新的单独问题的原因是因为我试图改编 Martijn Pieters 的great answer,但没有成功。

这是 MWE:

def grouper(sequence):
    result = []  # will hold (members, group) tuples

    for item in sequence:
        for members, group in result:
            if members.intersection(item):  # overlap
                members.update(item)
                group.append(item)
                break
        else:  # no group found, add new
            result.append((set(item), [item]))

    return [group for members, group in result]


gr = [[29, 27, 26, 28], [31, 11, 10, 3, 30], [71, 51, 52, 69],
      [78, 67, 68, 39, 75], [86, 84, 81, 82, 83, 85], [84, 67, 78, 77, 81],
      [86, 68, 67, 84]]

for i, group in enumerate(grouper(gr)):
    print 'g{}:'.format(i), group

我得到的输出是:

g0: [[29, 27, 26, 28]]
g1: [[31, 11, 10, 3, 30]]
g2: [[71, 51, 52, 69]]
g3: [[78, 67, 68, 39, 75], [84, 67, 78, 77, 81], [86, 68, 67, 84]]
g4: [[86, 84, 81, 82, 83, 85]]

最后一组g4 应该与g3 合并,因为其中的列表共享项目818384,即使是一个重复的元素也应该足以让它们合并。

我不确定是我应用代码错误,还是代码有问题。

【问题讨论】:

  • 我不认为你做错了什么;该代码不处理由于遇到事物的顺序而存在级联合并的情况。 (例如,grouper([[1,1],[1,2],[2,2]]) 有效,但 grouper([[1,1],[2,2],[1,2]]) 无效。

标签: python algorithm grouping


【解决方案1】:

您可以将要执行的合并描述为集合合并或连接组件问题。我倾向于使用现成的集合合并算法,然后使其适应特定情况。例如,IIUC,你可以使用类似的东西

def consolidate(sets):
    # http://rosettacode.org/wiki/Set_consolidation#Python:_Iterative
    setlist = [s for s in sets if s]
    for i, s1 in enumerate(setlist):
        if s1:
            for s2 in setlist[i+1:]:
                intersection = s1.intersection(s2)
                if intersection:
                    s2.update(s1)
                    s1.clear()
                    s1 = s2
    return [s for s in setlist if s]

def wrapper(seqs):
    consolidated = consolidate(map(set, seqs))
    groupmap = {x: i for i,seq in enumerate(consolidated) for x in seq}
    output = {}
    for seq in seqs:
        target = output.setdefault(groupmap[seq[0]], [])
        target.append(seq)
    return list(output.values())

给了

>>> for i, group in enumerate(wrapper(gr)):
...     print('g{}:'.format(i), group)
...     
g0: [[29, 27, 26, 28]]
g1: [[31, 11, 10, 3, 30]]
g2: [[71, 51, 52, 69]]
g3: [[78, 67, 68, 39, 75], [86, 84, 81, 82, 83, 85], [84, 67, 78, 77, 81], [86, 68, 67, 84]]

(由于使用字典,无法保证订单。)

【讨论】:

  • 很好的答案 DSM,您甚至解决了我不知道的问题。谢谢!
  • 现成的! - 大概吧。我编写了任务和迭代 Python 解决方案,Rosetta Code 的其他成员用所有其他示例将其充实。看看@Gabriel 的网站,还有很多来自:-)
【解决方案2】:

如果你把每个子列表变成一个集合,听起来就像集合合并,因为你对内容感兴趣而不是顺序,所以集合是最好的数据结构选择。看到这个:http://rosettacode.org/wiki/Set_consolidation

【讨论】:

    猜你喜欢
    • 2014-09-03
    • 2015-05-01
    • 2022-08-16
    • 2013-12-05
    • 1970-01-01
    • 2013-04-24
    • 2023-02-07
    • 2013-09-12
    • 2019-11-20
    相关资源
    最近更新 更多