我有一些代码,其中边缘表示为元组
(vertex_1, vertex_2)
我有表示平面嵌入面的边列表,如下例所示。
我需要搜索列表中是否存在边缘,但如果使用(v1, v2)
和(v2, v1)
,我需要返回true:
f1 = [(6, 1), (1, 2), (2, 7), (7, 6)]
(6,1) in f1
(1,6) in f1
True
False
答案 0 :(得分:3)
您无法覆盖现有类型的相等方法,因此您必须创建自己的类型,然后需要使用自定义类型替换所有现有元组。
如果你的主要问题只是(6,1) in f1
用例,那么也许你应该考虑为此创建一个方法:
def contains(t, lst):
return (t[0], t[1]) in lst or (t[1], t[0]) in lst
然后你可以像这样使用它:
>>> f1 = [(6, 1), (1, 2), (2, 7), (7, 6)]
>>> contains((6, 1), f1)
True
>>> contains((1, 6), f1)
True
这实际上有一个好处,就是您不需要用不同的类型替换元组。因此,您可以按原样使用所有数据源。
答案 1 :(得分:1)
你应该创建一个元组子类并改变它的相等方法(__eq__
):
class UnorderedTuple(tuple):
def __eq__(self, other):
return len(self) == len(other) and set(self) == set(other)
将适用于您的情况(元组长度== 2,如果元组元素是可以清除的 - 这是不可变的并具有明确定义的比较)
要将元组列表转换为无序元组列表,请执行以下操作:
f1 = [UnorderedTuple(f_) for f_ in f1]
要对列表进行适当的包含查询(in
运算符)可能会很慢 - 所以你最好有一个集合而不是列表:
set_f1 = { UnorderedTuple(f_) for f_ in f1 }
(6,1) in set_f1
(1,6) in set_f1
此实现不会非常高效,因为它会为每个比较创建一个新的set
。因此,如果你的元组总是两个元素,那么将__eq__
方法解压缩就更有效了:
def __eq__(self, other):
return super(UnordoredTuple, self).__eq__(other) or (self[0] == other[1] and self[1] == other[0])
答案 2 :(得分:1)
"是否可以为元组重新定义相等的运算符"
排序。您无法在基本tuple
类型上执行此操作,但您可以在子类上执行此操作:
class MyTuple(tuple):
def __eq__(self, other):
orig_eq = super(MyTuple, self).__eq__(other)
if orig_eq and orig_eq is not NotImplemented:
return True
else:
return super(MyTuple, self).__eq__(other[::-1])
通常,这可能不是最好的方法。根据问题的限制,您可以尝试一组freezeset:
f1_set = {frozenset(tup) for tup in f1}
frozenset((1, 6)) in f1_set
这里的优势在于,如果您对同一数据进行多个成员资格测试,您可能会获得更好的运行时间(列表上的每个成员资格测试都是O(N)
,您需要这样做对于您要检查的每个项目最多两个,而您只有一个O(N)
步骤来构建f1_set
,然后每个成员资格测试都是O(1)
。
答案 3 :(得分:0)
<div class="container-fluid">
<div class="row content">
<div class="col-sm-3 sidenav hidden-xs">
<h2>DRFM Cockpit</h2>
<ul class="nav nav-pills nav-stacked">
<li><a ng-controller="functionalitiesHandler" ng-click="setMDRFunction()" >MDR</a></li>
<li><a ng-controller="functionalitiesHandler" ng-click="setADRFunction()" >ADR</a></li>
</ul>
<br>
</div>
<br>
<div class="col-sm-9">
<div ng-if="MDR">
<h1>Test 1</h1>
<p>Test 1</p>
<hr>
</div>
<div ng-if="ADR">
<h1>Test 2</h1>
<p>Test 2</p>
<hr>
</div>
</div>
</div>
</div>
比你必须使用:
class new_tuple:
...
我认为使用函数来确定元组是否在列表中更容易:
tuple = (1,6)
tuple = new_tuple(tuple)
答案 4 :(得分:0)
此问题的一般解决方案是使用multisets,它们是元素可能出现多次的集合。 -bash: exportToAndroid.sh: command not found
模块定义了collections
类,它是Counter
的子类,实现了多重集。 dict
键是多集的元素,值是键出现的次数。
这避免了对多集中元素数量的限制,并且已经可用。主要的缺点是我所知道的没有“冻结”,可清洗的版本。
示例:
dict
您可以直接使用>>> from collections import Counter
>>> Counter((3, 6, 2, 4, 2, 8)) == Counter((8, 4, 3, 6, 2, 2))
True
>>> Counter((3, 6, 2, 4, 2, 8)) == Counter((8, 4, 3, 6, 4, 2))
False
类,这可能是最简单的,但如果您想保留基础Counter
表示,则可以使用tuple
类来实现更一般的其他人提出的Counter
子类的版本:
tuple
示例:
class MultisetTuple(tuple):
def __eq__(self, other):
return Counter(self) == Counter(other)