“无向”元组比较

时间:2014-01-09 19:44:31

标签: python tuples

我目前正在使用python中的无向图,其中边是由元组表示的(A和B之间的边由(A,B)或(B,A)表示)。我想知道是否有一个元组操作执行这样的元组的无向比较:

exp1 = undirected_comp((A,B), (B,A))    #exp1 should evaluate to True
exp2 = undirected_comp((A,B), (A,C))    #exp2 should evaluate to False

4 个答案:

答案 0 :(得分:4)

不完全一样,但一般来说,你可以与

进行这种比较
set (A,B) == set (B, A)

答案 1 :(得分:3)

不确定: undirected_comp = lambda e1,e2: e1==e2 or (e1[1],e1[0])==e2

因为边缘总是正好是2元组,所以它应该足够健壮,假设A和B对象定义了相等。

编辑(无耻的自我提升):您可能不希望为每个比较器创建两个set对象的开销,特别是如果这是更大算法的一部分。集合非常适合查找,但实例化速度要慢得多:https://stackoverflow.com/a/7717668/837451

答案 2 :(得分:3)

除了使用集合的解决方案之外,还可以轻松推出自己的比较功能:

In [1]: def undirected_comp(tup1, tup2):
   ...:     return tup1 == tup2 or tup1 == tup2[::-1]

In [2]: undirected_comp(('A','B'), ('B','A'))
Out[2]: True

In [3]: undirected_comp(('A','B'), ('A','C'))
Out[3]: False

In [4]: undirected_comp(('A','B'), ('A','B'))
Out[4]: True

正如mmdanziger所指出的,这比使用集合的解决方案更快,因为您不必支付集合创建的成本。

但如果您关心速度,您花费更多时间来比较各种边缘而不是创建它们,最好不要将边缘存储为具有任意顺序的元组,而是预先处理它们并以不同的格式存储它们。两个最佳选项可能是frozenset或排序元组(即按照惯例,您始终首先存储最小的节点)。一些快速的时机:

# edge creation, this time is spent only once, so presumably we don't care:
In [1]: tup1 = (1, 2); tup2 = (2, 1)
In [2]: fs1 = frozenset(tup1); fs2 = frozenset(tup2)
In [3]: sorted_tup1 = tuple(sorted(tup1)); sorted_tup2 = tuple(sorted(tup2))

# now time the comparison operations
In [4]: timeit set(tup1) == set(tup2) # Corley's solution
1000000 loops, best of 3: 674 ns per loop

In [5]: timeit tup1 == tup2 or tup1 == tup2[::-1] # my solution above
1000000 loops, best of 3: 348 ns per loop

In [6]: timeit fs1 == fs2 # frozensets
10000000 loops, best of 3: 120 ns per loop

In [7]: timeit sorted_tup1 == sorted_tup2 # pre-sorted tuples
10000000 loops, best of 3: 83.4 ns per loop

因此,假设您不关心边的创建时间,将它们存储为已排序的元组是进行比较最快的。在这种情况下,您只需要进行简单的比较,而不必比较后向情况,因为订单是通过预先排序保证的。

答案 3 :(得分:1)

Python元组是有序的,而python集则不是。您可以使用set在比较之前将元组转换为集合。

(A,B) == (B,A))          # evaluates to false
set((A,B)) == set((B,A)) # evaluates to true
set((A,B) == set((A,C))  # evaluates to false

如果你想使用一个函数,你可以这样做:

def undirected_comp(a,b):
     return (set(a) == set(b))

编辑:我正在使用cmp()进行比较,这是不正确的,因为如果为true则返回1,如果为false则返回-1,而不是布尔值。将函数更改为使用==,它应返回布尔值 - 如果您需要1-1,请使用return cmp(set(a), set(b))