2009-10-12 14 views
6

Soy nuevo Python y tratar de implementar el código de una manera más eficiente Pythonic y la moda. Dado un diccionario con claves y valores numéricos, ¿cuál es la mejor manera de encontrar la llave grande con un valor distinto de cero?manera eficiente para encontrar la clave más grande en un diccionario con valor distinto de cero

Gracias

+0

tal vez debería utilizar una estructura de datos más apropiado, como por ejemplo un montón, para recuperar los valores mín/máx en una colección. – Juliet

+1

"Más Pythonic" que qué? ¿Cuál es tu solución actual? ¿Qué no te gusta de eso? –

Respuesta

12

Algo como esto debe ser razonablemente rápido:

>>> x = {0: 5, 1: 7, 2: 0} 
>>> max(k for k, v in x.iteritems() if v != 0) 
1 

(. Retirar el != 0 será ligeramente más rápido todavía, pero oscurece el significado algo) función max

+2

Dado que el OP es nuevo, una descripción de lo que está sucediendo podría ser útil también. –

+6

Tenga en cuenta que en Python 3.x '.iteritems' ya no existe y' .items' devuelve un iterador. (A diferencia de Python 2.x, donde '.items' devuelve una lista y' .iteritems' devuelve un iterador.) – Stephan202

+3

¿Qué está pasando aquí? Estamos llamando a max() para encontrar la clave más grande. Lo que pasamos a max() es una "expresión generadora", muy similar a una "lista de comprensión". max() repetidamente obtendrá valores para k, y elegirá el más grande. La expresión del generador solo devolverá k valores cuando el valor v no sea cero. Los valores k y v provienen de x.iteritems(), que devuelve clave, pares de valores. Este código funcionará en Python 2.4 y más reciente, pero como señaló Stephan202, para Python 3.x necesita reemplazar "iteritems" con solo "elementos". – steveha

1

de Python toma una key= parámetro para una función "medida".

data = {1: 25, 0: 75} 
def keymeasure(key): 
    return data[key] and key 

print max(data, key=keymeasure) 

El uso de un lambda en línea en el mismo sentido y la misma unión de variables locales:

print max(data, key=(lambda k: data[k] and k)) 

última alternativa para atar en el var en la función clave en el anonimato

print max(data, key=(lambda k, mapping=data: mapping[k] and k)) 
+1

Esa función depende del acceso a lo global.Mala idea. –

+1

No, no es así. Eso solo depende de tener acceso al mismo alcance. Todo eso puede estar dentro de un alcance de función y aún así funcionaría. –

+2

@dalke, el punto es que la función debe tomar el diccionario como argumento, en lugar de codificar el nombre del dict. – steveha

10

Para obtener la clave más grande, puede utilizar la función max e inspeccionar las claves de esta manera:

max(x.iterkeys()) 

para filtrar aquellos en los que el valor es 0, se puede utilizar un generator expression:

(k for k, v in x.iteritems() if v != 0) 

Se pueden combinar estos para obtener lo que busca (ya max sólo toma un argumento, los paréntesis alrededor la expresión del generador se puede quitar):

max(k for k, v in x.iteritems() if v != 0) 
+2

¡Casi allí! Finalmente, quita las llaves cuadradas y te queda la mejor solución. Los corchetes cuadrados hacen una lista de comprensión, que construye toda la lista, y luego toda la lista se pasa a max(). Al salir de los corchetes cuadrados, obtienes una expresión de generador, que pasa los valores uno a la vez a max(). Para una pequeña cantidad de elementos no es gran cosa, pero para diccionarios muy grandes, el esfuerzo adicional para crear una lista y luego destruirla puede ser considerable. – steveha

+0

Acabo de actualizar mi respuesta ... cambié de listas a generadores/iteradores –

+2

Solo para tu información, no necesitas los parientes adicionales. Los parens de max() pueden hacer doble función: pueden ser los parens para la llamada de función a max() y también pueden ser los parens alrededor de la expresión del generador. ¡Intentalo! :-) – steveha

0

Si yo fuera usted y la velocidad era una gran preocupación, probablemente crearía una nueva clase de contenedor "DictMax" eso sería no perder de vista que es más grande valor distinto de cero elementos por tener una pila interna de ind exes, donde el elemento superior de la pila siempre es la clave del elemento más grande en el diccionario. De esta forma, obtendrías el elemento más grande en tiempo constante cada vez.

Cuestiones relacionadas