【问题标题】:Python combinations of overlapping pairs on a list列表上重叠对的 Python 组合
【发布时间】:2012-05-15 04:08:43
【问题描述】:

我将 Python 脚本作为 Hadoop 流式作业运行,但这篇文章更多地与一些核心 Python 概念相关,而不是关于 Hadoop 的知识。

基本上我有一组我想找到重叠的线

$ cat sample.txt
ID1    2143,2154,
ID2    2913,14545
ID3    2143,2390,3350,5239,6250
ID4    2143,2154,2163,3340
ID5    2143,2154,2156,2163,3340,3711

我想最后找到重叠的记录对并计算它们,例如这里是这样的:

2143,2154    3
2143,2163    2
2143,3340    2
2154,2163    2
2154,3340    2
2163,3340    2

我这样做的方法是创建一个用 Python 编写的 Hadoop 流作业,其中映射器基本上会输出给定行上的所有对组合,这些组合将由 reducer 进一步处理。

我的问题其实很简单:如何在 Python 中有效地生成给定行中所有对的组合?请注意,在我的情况下,一对 (x,y) 与一对 (y,x) 相同。例如对于ID3,我希望在我的映射器中生成以下列表:

[(2143,2390), (2143,2390), (2143,3350), (2143,5239), (2143,6250), (2390,3350), (2390,5239), (2390,6250), (3350,5239), (3350,6250), (5239,6250)]

我当然可以用一堆 for 循环来做到这一点,但它非常难看。我试过使用 itertools 但无法正确地从中得到一些东西。有什么想法吗?

【问题讨论】:

    标签: python hadoop combinations


    【解决方案1】:

    怎么样:

    x = [2143, 2390, 3350, 5239, 6250]
    itertools.combinations(x, 2)
    

    给予:

    (2143, 2390) (2143, 3350) (2143, 5239) (2143, 6250) (2390, 3350) (2390, 5239) (2390, 6250) (3350, 5239) (3350, 6250) (5239, 6250)
    

    【讨论】:

    • 这似乎也很好用,谢谢,与@aix 的生成器和ifilter 解决方案相比,有什么关于效率的想法吗?
    • (+1) 我认为这是最好的解决方案。
    • +1,但需要先排序,即combinations(sorted(x)
    • @thg435:问题中的数据已经排序,所以第二次排序没有好处
    • 作为仅供稍后阅读问题的人的参考,我最终使用了带有生成器的@aix 解决方案,因为我正在运行我的工作的 EMR 只有 Python 2.5.2,所以没有 @987654325 @,但我一直接受这一点,因为在另一种情况下,这是最好的解决方案。
    【解决方案2】:

    如果l 是有问题的列表

    [(x, y) for x in l for y in l if x < y]
    

    或者,您可以创建一个生成器:

    def pairs(l):
      for x in l:
        for y in l:
          if x < y:
            yield x, y
    

    这样做的好处是能够“动态”生成对,而不必同时将它们全部保存在内存中。

    使用itertools.product(l, l) 可以实现类似的效果,但这会同时生成(x, y) and (y, x),还会生成(x, x) 之类的对。要过滤掉这些,您必须执行以下操作:

    itertools.ifilter(lambda (x,y): x < y, itertools.product(l,l))
    

    【讨论】:

    • 很好,我喜欢生成器解决方案,我试图把它复杂化太多了! itertools 模块在这里也有用吗?
    • @linker:有点。 itertools.product() 非常接近。查看更新的答案。
    • 太好了,生成器一和itertools.ifilter 解决方案之间最有效的解决方案是什么?
    • 在所有 N**2 上循环以使用 if 丢弃一半的对似乎很浪费。
    【解决方案3】:

    小事有什么不好

    for i, x in enumerate(L):
        for y in L[i+1:]:
            whatever(x, y)
    

    ?

    这将调用whatever 传递来自L 的每对不同的元素(通过不同的我的意思是具有不同的索引,如果L 包含重复项,它们可能相等)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-05
      • 2013-04-25
      • 1970-01-01
      相关资源
      最近更新 更多