繁体   English   中英

集是否有“ dict.setdefault”等效项?

[英]Is there is 'dict.setdefault' equivalent for sets?

使用集合时的常见模式如下:

number_list = [1,5,7,2,4,4,1,3,8,5]
number_set = set()

for number in number_list:

   #we only want to process the number if we haven't already processed it
   if(number not in number_set):
       number_set.add(number)

       #do processing of 'number' here now that we know it's not a duplicate

if(number not in number_set):number_set.add(number)我的number_set.add(number)因为我们在这里进行了两次哈希查找,实际上,我们只需要一个哈希查找。

字典具有“ setdefault”操作,它解决了一个非常类似的问题:“如果字典中存在键,则返回值,否则插入该默认值,然后返回默认值”。 如果您天真地执行此操作(例如IE以下),则将执行两次哈希查找,但是setdefault允许您一次执行一次

if item_key in dict:
   dict[item_key].append(item_value)
else:
   dict[item_key] = [item_value]

集有等效的操作吗? if(number_set.check_if_contains_and_then_add(number)):但是给了一个更好的名字。

不,那里没有。

setdefault方法用于在字典中设置键的默认 ,而set没有值,因此完全没有意义。

如果顺序无关紧要,请尝试此方法。

number_list = [1,5,7,2,4,4,1,3,8,5]
number_set = set(number_list)

for number in number_set:
   #do processing of 'number' here now that we know it's not a duplicate

如果探查器告诉您哈希查找对运行时有重要作用,则可能可以解决此问题。

def add_value(container, value):
    oldlen = len(container)
    container.add(value)
    return len(container) != oldlen

if add_value(number_set, number):
    # process number

但是为什么会这样呢? 也许是由于__hash__方法很慢,尽管我现在可以告诉您(a)哈希整数并不慢,并且(b)如果可能的话,最好让__hash__慢的类缓存结果而不是减少通话次数。 也许是由于__eq__较慢,这很难处理。 最后,如果内部查找机制本身很慢,那么您可能无法做很多事情来加快程序的速度,因为运行时一直在进行哈希查找,在作用域中查找名称。

set.add返回一个值,该值指示集合是否更改可能会很好,但是我认为这种想法违背了Python库的原理(公认地,不是普遍支持的),即变异操作不会返回值除非这样做对操作至关重要。 因此pop()函数当然会返回一个值,但list.sort()返回None即使返回self偶尔对用户有用。

我想你可以做这样的事情:

def deduped(iterable):
    seen = set()
    count = 0
    for value in iterable:
        seen.add(value)
        if count != len(seen):
            count += 1
            yield value

for number in deduped(number_list):
    # process number

当然,纯粹是推测重复的哈希查找是什么问题:我通常会使用原始代码中if not in测试的方式编写这些函数中的任何一个,而该函数的目的是简化调用代码,不避免多余的哈希查找。

你为什么不只做number_set.add(number) setdefault的要点是,它不会覆盖键的现有值(如果存在)。 但是集合没有值,只有键,因此覆盖无关紧要。

不, sets没有setdefault类型方法,但是您可以执行以下操作:

number_list = [1,5,7,2,4,4,1,3,8,5]
number_set = set()

for number in number_list:
   if number not in number_set and not number_set.add(number):
       #do somethihng here

仅当number not in number_setTrue才会调用not number_set.add(number)条件。

使用此功能,您可以按有序方式处理唯一项目(保留订单)。

>>> number_list = [1,5,7,2,4,4,1,3,8,5]
>>> seen = set()
>>> [x for x in number_list if x not in seen and not seen.add(x)]
[1, 5, 7, 2, 4, 3, 8]

如果顺序无关紧要,则只需在number_list上调用set()

>>> set(number_list)
{1, 2, 3, 4, 5, 7, 8}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM