Как получить произвольный элемент из замороженного набора?

Я хотел бы получить элемент из frozenset (конечно, не изменяя его, поскольку frozenset неизменяемы). Лучшее решение, которое я нашел до сих пор, это:

s = frozenset(['a'])
iter(s).next()

который возвращает, как и ожидалось:

'a'

Другими словами, есть ли способ «вытолкнуть» элемент из frozenset, не выталкивая его на самом деле?


person ablondin    schedule 23.07.2013    source источник
comment
Я думаю, что ваш метод так же хорош, как и любой другой. Если вам нужен случайный элемент, вы можете проверить random.sample(fset, 1).   -  person bbayles    schedule 23.07.2013
comment
Почему вы хотите вытолкнуть элемент, потому что он произвольный?   -  person martineau    schedule 23.07.2013
comment
Я просто хочу получить произвольный элемент из замороженного набора. Я не должен был использовать слово «поп», так как набор остается неизменным. Это похоже на просмотр первого элемента стека без его извлечения.   -  person ablondin    schedule 23.07.2013
comment
Это то, что я использую (но со встроенным next вместо метода).   -  person user2357112 supports Monica    schedule 23.07.2013
comment
Не используйте метод .next(). Существует встроенная функция next(), так как по крайней мере python2.6 и ее использование означает, что ваш код будет работать также в python3, где метод next был переименован в __next__.   -  person Bakuriu    schedule 23.07.2013
comment
@user2357112 и @Bakuriu: Спасибо за ваши ответы, особенно Бакуриу за объяснение разницы между next(iter(fset)) и iter(fset).next().   -  person ablondin    schedule 23.07.2013
comment
@ Bo102010 random.sample(fset, 1) возвращает список; вам нужно random.sample(fset, 1)[0], чтобы получить сам элемент.   -  person Zero Piraeus    schedule 25.07.2013


Ответы (4)


(Обобщая ответы, данные в комментариях)

Ваш метод так же хорош, как и любой другой, с той оговоркой, что начиная с Python 2.6 вы должны использовать next(iter(s)), а не iter(s).next().

Если вам нужен элемент случайный, а не произвольный, используйте следующее:

import random
random.sample(s, 1)[0]

Вот несколько примеров, демонстрирующих разницу между ними:

>>> s = frozenset("kapow")
>>> [next(iter(s)) for _ in range(10)]
['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']
>>> import random
>>> [random.sample(s, 1)[0] for _ in range(10)]
['w', 'a', 'o', 'o', 'w', 'o', 'k', 'k', 'p', 'k']
person Zero Piraeus    schedule 24.07.2013
comment
Почему вы должны звонить next(iter(s)), а не iter(s).next()? - person rynemccall; 17.01.2015
comment
@rynemccall Потому что в Python 3 iter.next() не существует. - person Zero Piraeus; 17.01.2015

Если вы знаете, что во замороженном наборе есть только один элемент, вы можете использовать итерируемую распаковку:

s = frozenset(['a'])
x, = s

Это несколько частный случай исходного вопроса, но иногда он бывает полезен.

Если у вас их много, это может быть быстрее, чем next(iter..:

>>> timeit.timeit('a,b = foo', setup='foo = frozenset(range(2))', number=100000000)
5.054765939712524
>>> timeit.timeit('a = next(iter(foo))', setup='foo = frozenset(range(2))', number=100000000)
11.258678197860718
person Dominic Kempf    schedule 28.06.2016
comment
ValueError: too many values to unpack на множестве элементов. - person A T; 27.12.2016
comment
как сказано, это работает только с ровно одним элементом во замороженном наборе. - person Dominic Kempf; 10.01.2017

Вы можете использовать с python 3:

>>> s = frozenset(['a', 'b', 'c', 'd'])
>>> x, *_ = s
>>> x
'a'
>>> _, x, *_ = s
>>> x
'b'
>>> *_, x, _ = s
>>> x
'c'
>>> *_, x = s
>>> x
'd'
person tammoj    schedule 05.05.2017

Использование list:

list_ = list(frozenset("Benyamin"))

Использование generator:

def get_frozenset_elements(frozen_set):
    for i in frozen_set:
        yield i

gen_ = get_frozenset_elements(frozenset("Benyamin"))
next(gen_)
next(gen_)
next(gen_)
...

Использование iterator:

iter_ = iter(frozenset("Benyamin"))
next(gen_)
next(gen_)
next(gen_)
...

[ПРИМЕЧАНИЕ]:

Разница между генераторами и итераторами Python

person Benyamin Jafari    schedule 21.11.2019
comment
Первый из них — это просто сложный способ записи list(my_frozenset), что довольно расточительно для больших наборов. Второй - это просто сложный способ написать next(iter(my_frozenset)), который уже является принятым ответом. - person wchargin; 06.01.2020