我目前正在使用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
答案 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))
。