Acceda a un elemento arbitrario en un diccionario en Python

507

Si a mydictno está vacío, accedo a un elemento arbitrario como:

mydict[mydict.keys()[0]]

¿Hay alguna forma mejor de hacer esto?

Stan
fuente
3
Lo que dijo ... esta es realmente una pregunta válida si solo hay un elemento en el dict, o si no te importa cuál regresas.
real
55
Sí, solo necesito acceder a cualquier elemento en el dict, así que es por eso que quiero acceder al primer elemento.
Stan
2
@Stan: pero como dijo Greg, no hay un "primer" elemento definido en el dict. así que tal vez deberías cambiar tu pregunta, solo para que quede claro
tdihp
10
Creo que es una pregunta válida. Si necesita acceder a un elemento arbitrario, y está seguro de que el dict no está vacío, puede ser una buena idea pedir el "primero", porque es posible que no se conozca el número de elementos.
kap
77
@MichaelScheper tienen que desechar a la lista: list(mydict.keys())[0].
Daniel Moskovich

Respuestas:

600

En Python 3, de forma no destructiva e iterativa:

next(iter(mydict.values()))

En Python 2, de forma no destructiva e iterativa:

mydict.itervalues().next()

Si desea que funcione tanto en Python 2 como en 3, puede usar el sixpaquete:

six.next(six.itervalues(mydict))

aunque en este punto es bastante críptico y prefiero tu código.

Si desea eliminar algún elemento, haga lo siguiente:

key, value = mydict.popitem()

Tenga en cuenta que "primero" puede no ser un término apropiado aquí porque dictno es un tipo ordenado en Python <3.6. Python 3.6+ dictsestán ordenados.

doble
fuente
35
No quiere decir dict.iterkeys().next()?
John Machin
12
@ John Machin: Bueno, la pregunta parece tener acceso al valor asociado con la primera clave, así que eso es lo que hago también en la respuesta.
doublep
55
esto se ve mejor: dict.values().__iter__().__next__():)
Vitaly Zdanevich
17
Es molesto que dict.keys () no sea directamente iterable.
semiomante
3
para un popitem no destructivo se puede hacer una (superficial) copiar:key, value = dict(d).popitem()
Pelle
140

Si solo necesita acceder a un elemento (siendo el primero por casualidad, ya que los dictados no garantizan el pedido), simplemente puede hacer esto en Python 2 :

my_dict.keys()[0]     -> key of "first" element
my_dict.values()[0]   -> value of "first" element
my_dict.items()[0]    -> (key, value) tuple of "first" element

Tenga en cuenta que (a mi leal saber y entender) Python no garantiza que 2 llamadas sucesivas a cualquiera de estos métodos devuelvan la lista con el mismo orden. Esto no es compatible con Python3.

en Python 3 :

list(my_dict.keys())[0]     -> key of "first" element
list(my_dict.values())[0]   -> value of "first" element
list(my_dict.items())[0]    -> (key, value) tuple of "first" element
swK
fuente
90
Eso solo funciona en Python 2.x, para 3.x tienes que usarlist(my_dict.keys())[0]
alldayremix
66
Entonces, ¿qué clase de complejidad es esta? Seguramente, list(my_dict.keys())[0]no es vago?
Evgeni Sergeev
1
Para aclarar, lo que @alldayremix quiso decir con ese comentario está en python 3.x my_dict.function () los resultados no son compatibles con la indexación, es por eso que primero debemos convertirlo en una lista y luego podemos usar el índice [0]
Noki
57

En python3, El camino:

dict.keys() 

devuelve un valor en tipo: dict_keys (), obtendremos un error cuando obtengamos el primer miembro de las claves de dict de esta manera:

dict.keys()[0]
TypeError: 'dict_keys' object does not support indexing

Finalmente, convierto dict.keys () a list @ 1st, y obtuve el primer miembro por el método de empalme de lista:

list(dict.keys())[0]
Xb74Dkjb
fuente
Esta es la solución más fácil y funciona tanto en python2 como en python3.
mattmilten
Por mi dinero. Yo digo que esta respuesta es la más intuitiva
Thomas Valadez
Sí, pero esto no responde a la pregunta OP, que es cómo llegar a los VALORES, no a las claves.
Mike Williamson
1
@MikeWilliamson, con suerte, la mayoría de los lectores sabrán cómo obtener el valor correspondiente, dada una clave, de un dict de Python.
Eric
55
Para obtener un elemento arbitrario, no una clave arbitraria, puede hacerlo de forma análoga list(dict.values())[0].
jhin
24

obtener una llave

next(iter(mydict))

para obtener un valor

next(iter(mydict.values()))

para obtener ambos

next(iter(mydict.items())) # or next(iter(mydict.viewitems())) in python 2

Los dos primeros son Python 2 y 3. Los dos últimos son vagos en Python 3, pero no en Python 2.

maxbellec
fuente
16

Como otros mencionaron, no hay un "primer elemento", ya que los diccionarios no tienen un orden garantizado (se implementan como tablas hash). Si desea, por ejemplo, el valor correspondiente a la clave más pequeña, thedict[min(thedict)]lo hará. Si le importa el orden en que se insertaron las claves, es decir, por "primero" quiere decir "insertado más temprano", entonces en Python 3.1 puede usar collections.OrderedDict , que también se encuentra en Python 2.7; para versiones anteriores de Python, descargue, instale y use el backport dict ordenado (2.4 y posterior) que puede encontrar aquí .

Python 3.7 Ahora los dictados están ordenados por inserción.

Alex Martelli
fuente
11

Qué tal esto. No se menciona aquí todavía.

py 2 y 3

a = {"a":2,"b":3}
a[list(a)[0]] # the first element is here
>>> 2
animaacija
fuente
55
dict.values()devuelve una vista, por lo que debería ser O (1). list(a)devuelve una nueva lista, por lo que sería O (n).
boycy
También parece que no funciona en python2 si a = {"a": {"1"}}
qasimzee
11

Ignorando los problemas relacionados con el pedido de dict, esto podría ser mejor:

next(dict.itervalues())

De esta forma, evitamos la búsqueda de elementos y generamos una lista de claves que no usamos.

Python3

next(iter(dict.values()))
Matt Joiner
fuente
2
valores () hará una copia de todos los valores (al igual que las teclas () para las teclas), por lo que esto hará muchas operaciones O (n ^ 2).
Glenn Maynard
Entonces, ¿será la versión de OP? Cambiaré esto para usar un iterador entonces.
Matt Joiner el
44
Esto es solo Python 2. Para Python 3, necesitamos next(iter(dict.values()))obtener el mismo resultado sin crear la lista.
kap
6

En python3

list(dict.values())[0]
Oleg Matei
fuente
44
¿Qué sucede si el diccionario tiene mil millones de entradas? :)
Fábio Dias
2

Siempre puedes hacer:

for k in sorted(d.keys()):
    print d[k]

Esto le dará una forma consistente ordenados (con respecto al orden interna conjunto .hash () supongo) de teclas que puede procesar en la clasificación si tiene algún significado para ti. Eso significa, por ejemplo, que los tipos numéricos se ordenan de manera consistente incluso si expande el diccionario.

EJEMPLO

# lets create a simple dictionary
d = {1:1, 2:2, 3:3, 4:4, 10:10, 100:100}
print d.keys()
print sorted(d.keys())

# add some other stuff
d['peter'] = 'peter'
d['parker'] = 'parker'
print d.keys()
print sorted(d.keys())

# some more stuff, numeric of different type, this will "mess up" the keys set order
d[0.001] = 0.001
d[3.14] = 'pie'
d[2.71] = 'apple pie'
print d.keys()
print sorted(d.keys())

Tenga en cuenta que el diccionario se ordena cuando se imprime. ¡Pero el conjunto de claves es esencialmente un hashmap!

Philipp Meier
fuente
2

Para Python 2 y 3:

import six

six.next(six.itervalues(d))
oblalex
fuente
Esto no proporciona una respuesta a la pregunta. Para criticar o solicitar una aclaración de un autor, deje un comentario debajo de su publicación.
Martin Tournoij
Esto responde exactamente la pregunta Is there any better way to do this?de manera breve.
oblalex
Esta respuesta ya se ha dado dos veces, una de las cuales ha estado en este sitio durante casi 5 años. Este es un comentario sobre otra respuesta (como en: aquí se explica cómo mejorar la respuesta para que funcione con Python 2 y 3 ), y no una respuesta "nueva", como tal. El sistema de revisión de SO colocó automáticamente una nota algo inútil en este caso ...
Martin Tournoij
No señor. Agregó esta variante a su respuesta de 5 años hace solo 17 horas, 1 hora después de que escribí esta respuesta. Intente usar 'buscar' en esta página para 'seis' palabras y encontrará solo 6 coincidencias solo en estas 2 respuestas. De todos modos, ¿esta respuesta realmente te molesta? Creo que esto podría ayudar a otras personas en el futuro y está bien. Entonces, ¿cuál es el trato?
oblalex
Eso es porque, en mi humilde opinión, esta respuesta debería haber sido una edición de esa publicación en primer lugar. Sin la edición, las personas tendrían que desplazarse varias páginas hacia abajo para ver su respuesta; ¿Crees que es más útil que editar una respuesta altamente votada que es casi exactamente la misma que la tuya?
Martin Tournoij
0
first_key, *rest_keys = mydict
usuario1994083
fuente
11
Gracias por este fragmento de código, que puede proporcionar una ayuda limitada e inmediata. Una explicación adecuada mejoraría en gran medida su valor a largo plazo al mostrar por qué esta es una buena solución al problema y lo haría más útil para futuros lectores con otras preguntas similares. Por favor, editar su respuesta a añadir un poco de explicación, incluyendo los supuestos realizados.
Suraj Rao
-1

Sin bibliotecas externas, funciona tanto en Python 2.7 como en 3.x:

>>> list(set({"a":1, "b": 2}.values()))[0]
1

Para la clave aribtrary simplemente omita .values ​​()

>>> list(set({"a":1, "b": 2}))[0]
'a'
Thomas Browne
fuente
-2

La subclasificación dictes un método, aunque no eficiente. Aquí, si proporciona un número entero, volverá d[list(d)[n]]; de lo contrario, acceda al diccionario como se esperaba:

class mydict(dict):
    def __getitem__(self, value):
        if isinstance(value, int):
            return self.get(list(self)[value])
        else:
            return self.get(value)

d = mydict({'a': 'hello', 'b': 'this', 'c': 'is', 'd': 'a',
            'e': 'test', 'f': 'dictionary', 'g': 'testing'})

d[0]    # 'hello'
d[1]    # 'this'
d['c']  # 'is'
jpp
fuente