2009-10-24 12 views
42

Recientemente encontré un escenario en el que si un conjunto solo contenía un elemento único, quería hacer algo con ese elemento. Para obtener el elemento, que se establecieron en este enfoque:¿Cómo extraer el miembro del conjunto de un solo miembro en python?

element = list(myset)[0] 

pero esto no es muy satisfactorio, ya que crea una lista innecesario. También podría hacerse con iteración, pero la iteración tampoco parece natural, ya que solo hay un elemento. ¿Me estoy perdiendo algo simple?

Respuesta

62

desempaquetado de tupla funciona.

(element,) = myset 

(Por cierto, python-dev ha explorado pero rechazó la adición de myset.get() para devolver un elemento arbitrario de un conjunto. Discussion here, Guido van Rossum responde 1 y 2.)

Mi favorito personal para conseguir elemento arbitrario es (cuando se tiene un número desconocido, pero también funciona si usted tiene sólo una):

element = next(iter(myset)) ¹ 

: en Python 2.5 y se acaben correo, usted tiene que utilizar iter(myset).next()

+6

muy agradable! Me gusta que esto falle si la cantidad de elementos no es 1. –

+0

@Laurence: es una buena observación. Captura errores temprano, ¿verdad? – u0b34a0f6ae

+2

O, si quiere pretender que Python tiene un operador adecuado para el trabajo (sus compañeros de trabajo lo odiarán): 'element, = myset' – rdb

2

puede utilizar element = tuple(myset)[0] que es un poco más eficiente, o bien, se puede hacer algo como

element = iter(myset).next() 

supongo que la construcción de un iterador es más eficiente que la construcción de una tupla/lista .

+0

¿Por qué crees que construir un iterador es más eficiente? –

+0

afortunadamente, te señalo la respuesta de Alex :) –

17

entre hacer una tupla y haciendo un iterador, es casi un lavado, pero gana iteración por una nariz ...:

$ 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 
No

seguro de por qué todas las respuestas están utilizando la sintaxis anterior iter(x).next() en lugar de la nuevo next(iter(x)), que me parece preferible (y también funciona en Python 3.1).

Sin embargo, victorias desembalaje de las manos hacia abajo sobre ambos:

$ 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 

Por supuesto, esto es para los conjuntos de un solo artículo (donde la última forma, como otros han dicho, tiene la ventaja de no ayuno si el conjunto que "Sabía" que solo había un objeto en realidad tenía varios). Para los conjuntos arbitrarios con N> 1 materiales, la tupla se ralentiza, el ITER no:

$ 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 

Así, desembalaje para el caso único, y next(iter(x)) para el caso general, parece mejor.

+0

¿Por qué la sintaxis de Python2.x? Solo realizo programación real allí, y 'python' es Python 2.5 en mi sistema, y ​​de ahí lo que aparece cuando presiono mi combinación de teclas para abrir una consola de python. – u0b34a0f6ae

+0

2.6 es perfectamente utilizable para "programación real" y más rica que 2.5; la única razón para quedarse con 2.5 es si su entorno externo lo restringe (App Engine, Civilization 4, etc.). next (x) y x.next() ambos funcionan en 2.6, pero el siguiente (x) es mejor (le permite especificar un valor predeterminado en lugar de detectar excepciones de StopIteration, requiere un carácter menos ;-). –

+0

@Alex: No es necesario que me convenza, preferiría usar Python 2.6. Yo uso Debian, ¡Debian aún no ha terminado de hacer la transición a Python 2.6! (Pyhthon 2.6 sí mismo está disponible, pero ninguna de las bibliotecas de 3ª parte de distribuciones.) – u0b34a0f6ae

11

Creo que kaizer.se's answer es genial. Pero si su conjunto podría contener más de un elemento y desea un elemento no tan arbitrario, es posible que desee utilizar min o max. Ej .:

element = min(myset) 

o:

element = max(myset) 

(No utilice sorted, debido a que tiene una sobrecarga innecesaria para este uso.)

2

sugiero:

element = myset.pop() 
+0

Esto podría funcionar en algunos casos, pero muta el conjunto. – recursive

Cuestiones relacionadas