【问题标题】:Creating a list of 'unioned' elements of another list创建另一个列表的“联合”元素列表
【发布时间】:2020-04-13 10:58:58
【问题描述】:

我在编程方面还有些稚嫩,遇到了一个绊脚石。

我有一个列表列表,我想组合嵌套列表中具有相似元素的元素。

列表列表:

    x = [[25, 26],[26, 27],[27, 28],[32, 33],[33, 34],[40, 41],[61, 62],[62, 63],[63, 64]]

我正在寻找的输出:

[[25,26,27,28],[32,33,34],[40,41],[61,62,63,64]]

我使用 lambda 函数、map、reduce 和 map-reduce 以几种不同的方式解决了这个问题。

  • 我尝试过使用交集的 lambda 函数进行映射,但它没有捕获 2 以上的所有元素。即。 x[0] 与 x[2] 没有交集

  • map-reduce 只给了我第一个集合和最后一个索引,我可以迭代这个,但是看起来很麻烦,它也会跳过没有类似相交子列表的子列表。 (下例)

mapped = [(idx, i) for idx, i in enumerate(x)]

reduce(lambda a,b: a if not set(a[1]).intersection(set(b[1])) else (a[0]+b[0],set(a[1]).union(set(b[1]))) ,mapped)

输出:

(3, {25, 26, 27, 28})

任何帮助将不胜感激,谢谢!

【问题讨论】:

  • 第一个问题:“相似”是一个模糊的术语。看来您的意思是 [[a,b],[b,c]] 形式的对,其中 c-b == b-a == 1。这是正确的吗?如果不是,你能定义“相似”吗?
  • 第二个问题:在你呈现数据的时候,要合并的子列表都是相邻且连续的。我们是否可以假设这通常是正确的,或者我们应该考虑到对的任意排序?
  • 嗨!是的,谢谢你的召唤。所有子列表都将按顺序排列。它们实际上是另一个文本行列表的索引,它们需要按顺序组合。要组合的子列表将彼此相邻并且“相似”,我的意思是前面的元素 x[n+1][0] == x[n][-1],并且当组合时每个子列表将是唯一序列号的列表。
  • 在这种情况下,在我看来,您的第一步是丢弃每对的第二个元素,因为这只是分散注意力,它会为您提供类似[25, 26, 27, 32, 33, 40, 61, 62, 63] 的列表。现在您只需在不连续点将其划分为子列表,并在每个子列表的末尾添加一个额外的“页面”。使用高阶函数(即 itertools)可能有一种可爱的方法可以做到这一点,但它也是一个简单的函数。
  • 或者,在概念上可能更简单,将列表展平,对其进行设置,并对结果进行排序。这当然不会更有效,但它可能会产生更清晰的代码,这通常更重要。

标签: python-3.x dictionary reduce


【解决方案1】:

我认为对于这类问题,命令式的解决方案是最直接的,而不是尝试使用推导式或高阶函数来解决。

这是一个构建列表列表的解决方案。每次我们看到一对新的[x, y],检查x 是否在当前列表的末尾。如果是,请将y 附加到该列表;否则,使用xy 开始一个新列表。

def join_pairs(pairs):
    out = []
    for x, y in pairs:
        if out and out[-1][-1] == x:
            out[-1].append(y)
        else:
            out.append([x, y])
    return out

例子:

>>> pairs = [
...     [25, 26], [26, 27], [27, 28], [32, 33], [33, 34],
...     [40, 41], [61, 62], [62, 63], [63, 64]
... ]
>>> join_pairs(pairs)
[[25, 26, 27, 28], [32, 33, 34], [40, 41], [61, 62, 63, 64]]

正如 Jon Kiparsky 在 cmets 中指出的那样,您示例中的对方便地相邻且连续。上面的解决方案取决于此;如果您的所有输入数据都不是这样,那么您需要先进行一些排序:

    for x, y in sorted(sorted(p) for p in pairs):
        # ...

【讨论】:

  • 谢谢你,它有效!不过问题 - 在 if 语句中。 “out”是“到目前为止”列表,您正在将列表“到目前为止”和最后一个列表中的最后一个数字与要检查的下一对中的第一个数字进行比较。那不应该永远等同于真实吗? IE。 '[[25, 26, 27, 28], [32,33]]' 和 '33' == '33'...真的吗?我的意思是.. 它有效,但为什么呢?
  • and 的优先级低于== - 像if (out) and (out[-1][-1] == x): 一样阅读。第一部分只是检查列表中是否有任何内容,否则out[-1] 将是 IndexError。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多