如果您希望允许重复,则需要一些额外的空间来跟踪事物。然而,现在的选择可以简化为重复列表或集合的空间。如果列表通常比集合大,第一个函数可以节省一些空间。但请注意:如果集合大于列表,则会占用更多空间。
s = set([ 1, 2, 3, 4 ])
l = [ 1, 2, 3, 5 ]
方法一:按照集合的顺序创建一个Counter
def low_space_compare(some_set, some_list):
from collections import Counter
state = Counter(some_set)
for item in some_list:
if item not in state:
print("bad")
return "bad"
state[item] -= 1
if any(val > 0 for val in state.values()): #change to val != 0 if duplicates not allowed
print("bad")
return "bad"
return "good"
另一方面,如果也不允许欺骗,您可以简单地遍历列表并从集合中删除,根本不需要额外的空间。但是它改变了集合!
方法2:没有多余的空间,不能处理欺骗
def low_space_compare_no_dupes(some_set, some_list):
#need to create a copy of some_set if you (hopefully) take offense to mutating the original set
for item in some_list:
if item not in some_set:
print("bad")
return "bad"
else:
some_set.remove(item) #this makes a dupe value fail when you see it again
if some_set:
print("bad, set had extra stuff")
return "bad"
return "good"
low_space_compare(s, l) #bad
low_space_compare_no_dupes(s, l) #bad
print(s) #{4} uh oh.
编辑:方法 3:最坏的情况与从列表 n 中创建一个新集合相同,在它有效匹配但短路的情况下:
def low_space_compare_no_counters(some_set, some_list):
new_set = set()
#need to create a copy of some_set if you (hopefully) take offense to mutating the original set
for item in some_list:
if item not in some_set:
if item not in new_set:
print("bad")
return "bad"
else:
pass #ah, a dupe, keep going
else:
some_set.remove(item)
new_set.add(item)
if some_set:
print("bad, set had extra stuff")
return "bad"
return "good"
low_space_compare_no_counters(s, l)