如何从单元素集合中提取成员?

119 投票
8 回答
49920 浏览
提问于 2025-04-15 15:21

我最近遇到了一个情况,就是当一个集合里只有一个元素时,我想对这个元素做点什么。为了获取这个元素,我采用了这个方法:

element = list(myset)[0]

不过这样做让我觉得不太满意,因为它创建了一个不必要的列表。其实也可以用循环来做,但用循环似乎也不太自然,因为里面只有一个元素。我是不是漏掉了什么简单的方法呢?

8 个回答

26

我觉得kaizer.se的回答非常不错。不过,如果你的集合可能包含多个元素,而你想要一个不那么随意的元素,那么你可以考虑使用min或者max。比如:

element = min(myset)

或者:

element = max(myset)

(不要使用sorted,因为这样做会增加不必要的开销。)

32

在创建元组和创建迭代器之间,差不多是一样的,但迭代器稍微胜出一点……:

$ python2.6 -mtimeit -s'x=set([1])' 'a=tuple(x)[0]'
1000000 loops, best of 3: 0.465 usec per loop
$ python2.6 -mtimeit -s'x=set([1])' 'a=tuple(x)[0]'
1000000 loops, best of 3: 0.465 usec per loop
$ python2.6 -mtimeit -s'x=set([1])' 'a=next(iter(x))'
1000000 loops, best of 3: 0.456 usec per loop
$ python2.6 -mtimeit -s'x=set([1])' 'a=next(iter(x))'
1000000 loops, best of 3: 0.456 usec per loop

我不明白为什么所有的回答都在用旧的写法 iter(x).next(),而不是新的写法 next(iter(x)),我觉得后者更好(而且在Python 3.1中也能用)。

不过,解包的方式明显比这两种都要好:

$ python2.6 -mtimeit -s'x=set([1])' 'a,=x'
10000000 loops, best of 3: 0.174 usec per loop
$ python2.6 -mtimeit -s'x=set([1])' 'a,=x'
10000000 loops, best of 3: 0.174 usec per loop

当然,这里说的是单个元素的集合(就像其他人提到的,后者的好处是如果你“知道”的集合其实有多个元素,它会很快报错)。对于包含多个元素的集合,元组的速度会变慢,而迭代器则不会:

$ python2.6 -mtimeit -s'x=set(range(99))' 'a=next(iter(x))'
1000000 loops, best of 3: 0.417 usec per loop
$ python2.6 -mtimeit -s'x=set(range(99))' 'a=tuple(x)[0]'
100000 loops, best of 3: 3.12 usec per loop

所以,对于单个元素的情况,解包是最好的,而对于一般情况,使用 next(iter(x)) 似乎是最合适的。

150

元组解包是有效的,它验证了一个假设:这个 set恰好 有一个元素(如果元素太多或太少,就会抛出 ValueError 错误)。

(element,) = myset
# Or equivalently, without requiring trailing comma:
[element] = myset

顺便提一下,python-dev 曾经探讨过但最终拒绝了添加 myset.get() 这个功能,以便从集合中返回一个任意元素。讨论在这里,Guido van Rossum 的回答可以看12

我个人最喜欢获取任意元素的方法是(当你不知道元素数量时也适用,如果只有一个元素也可以):

element = next(iter(myset)) ¹

1: 在 Python 2.5 及之前的版本中,你需要使用 iter(myset).next()

撰写回答