Как извлечь член из набора из одного члена в Python? - PullRequest
54 голосов
/ 25 октября 2009

Недавно я столкнулся со сценарием, в котором, если набор содержит только один элемент, я хотел что-то сделать с этим элементом. Чтобы получить элемент, я остановился на таком подходе:

element = list(myset)[0]

Но это не очень приятно, так как создает ненужный список. Это также может быть сделано с помощью итерации, но итерация также кажется неестественной, поскольку существует только один элемент. Я скучаю по чему-то простому?

Ответы [ 5 ]

80 голосов
/ 25 октября 2009

Работы по распаковке кортежей.

(element,) = myset

(Кстати, python-dev исследовал, но отклонил добавление myset.get() для возврата произвольного элемента из набора. Обсуждение здесь , Гвидо ван Россум отвечает 1 и 2 .)

Мой личный фаворит для получения произвольного элемента (когда у вас есть неизвестное число, но также работает, если у вас есть только один):

element = next(iter(myset)) ¹

1 : в Python 2.5 и более ранних версиях вы должны использовать iter(myset).next()

20 голосов
/ 25 октября 2009

Между созданием кортежа и созданием итератора это почти стирка, но итерация выигрывает носом ...:

$ 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

Это, конечно, для наборов из одного элемента (где последняя форма, как уже упоминалось, имеет преимущество быстрого отказа, если набор, о котором вы «знали», имел только один элемент, на самом деле имел несколько). Для наборов с произвольным числом элементов N> 1 кортеж замедляется, а iter не:

$ 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)) для общего дела кажутся наилучшими.

12 голосов
/ 20 декабря 2010

Я считаю kaizer.se ответ отлично. Но если ваш набор может содержать более одного элемента, и вам нужен элемент, не столь произвольный, вы можете использовать min или max. E.g.:

element = min(myset)

или

element = max(myset)

(Не используйте sorted, потому что это приводит к ненужным накладным расходам для этого использования.)

4 голосов
/ 19 апреля 2017

Я предлагаю:

element = myset.pop()
2 голосов
/ 25 октября 2009

вы можете использовать element = tuple(myset)[0], что немного более эффективно, или вы можете сделать что-то вроде

element = iter(myset).next()

Я думаю, что создание итератора более эффективно, чем создание кортежа / списка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...