有效地将列表与集合进行比较

时间:2019-04-24 05:55:04

标签: python list set compare

是否有一种更有效的方法来确保list包含set的所有且仅包含其他元素,然后从set构造另一个list? / p>

例如避免了复制列表和对列表进行排序

s = set([ 1, 2, 3, 4 ])
l = [ 1, 2, 3, 5 ]
if s!=set(l):
    print "bad list"

2 个答案:

答案 0 :(得分:3)

通过使用列表调用集合的symmetric_difference方法,可以避免从列表构造另一个集合:

if s.symmetric_difference(l):
    print "bad list"

答案 1 :(得分:1)

如果您希望允许重复,则需要某种额外的空间来跟踪事物。但是,现在可以将选择简化为重复列表或集合的空间。如果列表大于通常的列表,则第一个功能可以节省一些空间。但请注意:如果集合大于列表,则会占用更多空间。

s = set([ 1, 2, 3, 4 ])
l = [ 1, 2, 3, 5 ]

方法1:按集合顺序创建一个计数器

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)