断言两个列表清单的最佳方式是否相等,没有顺序的重要性?例如这两个列表是相等的:断言在Python中没有顺序的列表相等列表
a = [[1,2], [3,4]]
b = [[4,3], [2,1]]
assert lists_equal_without_order(a, b) # True
如何lists_equal_without_order
来实现,最好使用一些Python现有的断言?
断言两个列表清单的最佳方式是否相等,没有顺序的重要性?例如这两个列表是相等的:断言在Python中没有顺序的列表相等列表
a = [[1,2], [3,4]]
b = [[4,3], [2,1]]
assert lists_equal_without_order(a, b) # True
如何lists_equal_without_order
来实现,最好使用一些Python现有的断言?
如果a
或b
, 中的项目中没有重复项,则可以使用集合理解来收集每个项目的冻结集。 例如,
In [106]: {(frozenset(item)) for item in a}
Out[106]: {frozenset({1, 2}), frozenset({3, 4})}
然后测试,如果这些集合相等:
In [107]: {(frozenset(item)) for item in a} == {(frozenset(item)) for item in b}
Out[107]: True
此操作,因为集没有秩序,frozensets是哈希的(因此可以是一组的元件)。如果没有重复,然后frozenset平等,使[1,2]
和[2,1]
相当于:
In [109]: frozenset([1,2]) == frozenset([2,1])
Out[109]: True
但要注意的是,如果有重复,那么frozensets将使[1,1,2]
相当于[2,2,1]
:
In [108]: frozenset([1,1,2]) == frozenset([1,2,2])
Out[108]: True
好运行一个循环考虑清单的大小。
A =列表;
B =列表B;
对于i从0运行:环的尺寸
{ 温度= A [1];
如果(温度是在存在组B)从乙 删除临时;
}
如果B是空集则A = B;
否则 !A = B
感谢您的努力,但我正在专门寻找Python代码,并且我不确定您的解决方案是否可行。 –
如果性能是不是一个因素,一个简单的解决办法是先内部列表进行排序,然后外列表进行排序,然后对它们进行比较。
示例 -
def lewo(l1, l2):
l1new = [sorted(i) for i in l1]
l2new = [sorted(i) for i in l2]
l1newsorted = sorted(l1new)
l2newsorted = sorted(l2new)
return l1newsorted == l2newsorted
或者更简洁 -
def lewo(a, b):
a_s, b_s = map(sorted, a), map(sorted, b)
return sorted(a_s) == sorted(b_s)
我喜欢这种方法,在这里我看不到很大的性能损失。 –
一个版本,只有一束假设的作品:
def lists_equal_without_order(a, b):
"""
We don't care about duplicates in list comparison or the sublist comparison.
* [1,2,2] === [1,1,2] # True
* [[1,1], [1,1]] == [[1,1]] # True
The element lists are either the same length or we don't care about duplicates
* [1,1,1] === [1] # True
"""
for l1 in a:
check_list = frozenset(l1)
if not any(check_list.issuperset(l2) for l2 in b):
return False
return True
a = [[1,2], [3,4]]
b = [[4,3], [2,1]]
print lists_equal_without_order(a, b) # True
a = [[1,1], [2,2]]
b = [[1,2], [2,1]]
print lists_equal_without_order(a, b) # False
一个版本弄乱原始列表:
def lists_equal_without_order(a, b):
"""
This will manipulate the original lists.
"""
for l1 in a:
l1.sort()
for l2 in b:
l2.sort()
if l1 == l2:
b.remove(l2)
break
else:
return False
return True
a = [[1,2], [3,4]]
b = [[4,3], [2,1]]
print lists_equal_without_order(a, b) # True
a = [[1,1], [2,2]]
b = [[1,2], [2,1]]
print lists_equal_without_order(a, b) # False
一个版本,做设有专柜完全匹配,但并不需要保持名单的2份内存:
from collections import Counter
def lists_equal_without_order(a, b):
"""
This will make sure the inner list contain the same,
but doesn't account for duplicate groups.
"""
for l1 in a:
check_counter = Counter(l1)
if not any(Counter(l2) == check_counter for l2 in b):
return False
return True
a = [[1,2], [3,4]]
b = [[4,3], [2,1]]
print lists_equal_without_order(a, b) # True
a = [[1,1], [2,2]]
b = [[1,2], [2,1]]
print lists_equal_without_order(a, b) # False
我认为使用'sorted()'而不是'inplace'.sort()'会更好,我认为在断言期间导致实际数据改变并不合适。 –
@AnandSKumar绝对真实,JonClements刚发布的内容看起来很棒。 –
@AnandSKumar我有点无聊,并增加了两个解决方案。一个使用frozenset的灵感来自其他答案,但忽略了所有级别的重复项目和一个使用Counter。这些不需要创建列表的完整副本来进行比较。 –
如果在子列表没有重复(或复制可以忽略不计),这种方法的工作原理:
def lists_equal_without_order(a, b):
return set_repr(a) == set_repr(b)
def set_repr(x):
return {frozenset(item) for item in x}
如果我们需要考虑在子列表中重复的,我们需要改用frozensets的计数器:
from collections import Counter
def lists_equal_without_order(a, b):
return counter_repr(a) == counter_repr(b)
def counter_repr(x):
return {frozenset(Counter(item).items()) for item in x}
如果子列表本身可以出现多次(即,如果外部列表包含重复),我们可以用一个柜台外列表:
from collections import Counter
def lists_equal_without_order(a, b):
return counter_repr(a) == counter_repr(b)
def counter_repr(x):
return Counter(frozenset(Counter(item).items()) for item in x)
不同set/frozenset
方法:
a = [[1,2], [3,4]]
b = [[4,3], [2,1]]
def lists_equal_without_order(lst0, lst1):
set0 = set(frozenset(item) for item in lst0)
set1 = set(frozenset(item) for item in lst1)
return set0 == set1
print(lists_equal_without_order(a,b))
我不能完全肯定它涵盖了所有的用例。作品为你给的例子虽然...
我以为你是一个学生寻求作业的帮助,直到我看到你的代表。 ;) –
我假设你仍然希望允许重复(没有这样设置外部列表),我们可能不会假设元素的可哈希性或自然排序顺序? –
子列表的大小始终是2,大小相等还是大小可变? –