删除python集中的重复交互对

时间:2012-02-29 16:03:04

标签: python set tuples

假设你有一个python集中的元组列表:

>>> pairs = set( [(0,1),(0,1),(1,0)] )
>>> print pairs
set([(0, 1), (1, 0)])

显然,前两个元素是重复的并且相应 对于集合的定义,“对”只包含唯一元素。

但是,在我的特定情况下,元组(i,j)定义了一个交互对。从而, (i,j)和(j,i)是相同的。我需要一种有效的方法来减少所有重复 元素。计算时间对我来说至关重要,因为总计很容易包含大到10 ** 6的元素。我期待以下结果:

>>> pairs = set( [(0,1),(0,1),(1,0)] )
>>> pairs = remove_duplicate_interactions(pairs)
>>> print pairs
set([0,1]) or set([1,0])

我很感激任何提示。

编辑:

有人询问了背景。这应该用于粒子模拟。 由于对称条件,作用于j的粒子i的力与作用于i的j的力相同。因此,计算时间缩短了50%。

5 个答案:

答案 0 :(得分:9)

怎么样:

In [4]: pairs = set( [(0,1),(0,1),(1,0),(1,2),(1,0),(2,1)] )

In [5]: set((a,b) if a<=b else (b,a) for a,b in pairs)
Out[5]: set([(0, 1), (1, 2)])

答案 1 :(得分:3)

我会子类型tuple并且总是订购这对:

class InteractionPair(tuple):
    def __new__(cls, a, b):
        if a <= b:
            return tuple.__new__(cls, (a, b))
        return tuple.__new__(cls, (b, a))

示例:

>>> set([InteractionPair(0, 1), InteractionPair(1, 0)])
set([(0, 1)])

这也可以应用于标准元组列表:

from itertools import starmap
pairs = [(0, 1), (0, 1), (1, 0)]
print set(starmap(InteractionPair, pairs))

编辑:她是一些时间,使用1000000个随机对的列表:

In [14]: timeit set(starmap(InteractionPair, pairs))
1 loops, best of 3: 742 ms per loop

In [15]: timeit set((a,b) if a<=b else (b,a) for a,b in pairs)
1 loops, best of 3: 258 ms per loop

In [16]: timeit set(tuple(sorted(p)) for p in pairs)
1 loops, best of 3: 1.02 s per loop

就表现而言,solution by aix获胜。

答案 2 :(得分:2)

>>> pairs = [(0,1),(0,1),(1,0)]
>>> set(tuple(sorted(p)) for p in pairs)
set([(0, 1)])

答案 3 :(得分:1)

如果您可以使用frozenset而不是元组,则可以将每个交互对存储为一组。另一种方法是以一些规范形式存储所有元组(例如,i < j)。不知道这是否具有超过freezeset的速度优势,但是形式越简单,越快的python将能够散列它并计算一组独特的元素。

答案 4 :(得分:0)

pairs = set(frozenset(p) for p in ((0,1),(0,1),(1,0)) )

将实现您的需求。有关详细信息,请参阅我的回答:How do I perform deep equality comparisons of two lists of tuples?

如有必要,您可以在事后重建这些对象。