2009-10-07 21 views
10

He dict en Python con las llaves de la siguiente forma:¿Puedo ordenar texto por su valor numérico en Python?

mydict = {'0'  : 10, 
      '1'  : 23, 
      '2.0' : 321, 
      '2.1' : 3231, 
      '3'  : 3, 
      '4.0.0' : 1, 
      '4.0.1' : 10, 
      '5'  : 11, 
      # ... etc 
      '10' : 32, 
      '11.0' : 3, 
      '11.1' : 243, 
      '12.0' : 3, 
      '12.1.0': 1, 
      '12.1.1': 2, 
      } 

Algunos de los índices no tienen sub-valores, algunos tienen un nivel de sub-valores y algunos tienen dos. Si solo tuviera un subnivel, podría tratarlos a todos como números y ordenarlos numéricamente. El segundo subnivel me obliga a manejarlos todos como cadenas. Sin embargo, si los clasifico como cadenas tendré 10 siguiendo 1 y 20 siguiendo 2.

¿Cómo puedo ordenar los índices correctamente?

Nota: Lo que realmente quiero hacer es imprimir el dictado ordenado por índice. Si hay una forma mejor de hacerlo que ordenarlo de alguna manera, eso está bien conmigo.

+2

Esto se llama "clasificación natural". Consulte http://stackoverflow.com/questions/34518/natural-sorting-algorithm –

Respuesta

18

Puede ordenar las teclas de la manera que desea, dividiéndolos en ''. y luego la conversión de cada uno de los componentes en un entero, de esta manera:

sorted(mydict.keys(), key=lambda a:map(int,a.split('.'))) 

que devuelve esto:

['0', 
'1', 
'2.0', 
'2.1', 
'3', 
'4.0.0', 
'4.0.1', 
'5', 
'10', 
'11.0', 
'11.1', 
'12.0', 
'12.1.0', 
'12.1.1'] 

Puede iterar sobre esa lista de claves, y tire de los valores de su diccionario como necesario.

También puede ordenar el resultado de mydict.items(), muy parecida:

sorted(mydict.items(), key=lambda a:map(int,a[0].split('.'))) 

Esto le da una lista ordenada de (clave, valor) pares, como esto:

[('0', 10), 
('1', 23), 
('2.0', 321), 
('2.1', 3231), 
('3', 3), 
# ... 
('12.1.1', 2)] 
+0

Y, por supuesto, no necesita usar un lambda, puede definir una función de la manera habitual y pasar el nombre. – steveha

+0

Más rápido que la versión del comparador (menos conversiones/llamadas a funciones). – bobince

2

funciones de ordenación de Python pueden tomar una costumbre comparar la función, por lo que sólo tiene que definir una función que compara las llaves a su gusto:

def version_cmp(a, b): 
    '''These keys just look like version numbers to me....''' 
    ai = map(int, a.split('.')) 
    bi = map(int, b.split('.')) 
    return cmp(ai, bi) 

for k in sorted(mydict.keys(), version_cmp): 
    print k, mydict[k] 

En este caso, debería utilizar el parámetro key en sorted(), sin embargo. Vea la respuesta de Ian Clelland para un ejemplo de eso.

+1

Es mejor proporcionar la función clave que Ian. La función clave se llama una vez para cada elemento, la función cmp se llama cada vez que el género hace una comparación. –

+0

@gnibbler: Sí, me di cuenta de que después de leer la respuesta de Ian ... estaba pensando en eliminar mi respuesta, pero creo que podría ser útil para alguien que necesita una comparación más complicada que no se puede hacer pasando un simple ' clave'. – sth

2

Como una adición al Ian Clelland's respuesta, la llamada map() puede ser sustituida por una lista por comprensión ... si lo prefiere ese estilo. Es puede también ser más eficiente (aunque es insignificante en este caso, sospecho).

sorted(mydict.keys(), key=lambda a: [int(i) for i in a.split('.')])

1

Para la diversión & utilidad (por PPL googlear, en su mayoría):

f = lambda i: [int(j) if re.match(r"[0-9]+", j) else j for j in re.findall(r"([0-9]+|[^0-9]+)", i)] 
cmpg = lambda x, y: cmp(f(x), f(y)) 

uso como sorted(list, cmp=cmpg). Además, las expresiones regulares pueden compilarse previamente (raramente es necesario, en realidad, con el almacenamiento en caché del módulo re). Y, puede ser (fácilmente) modificado, por ejemplo, para incluir valores negativos (agregar -? a num. Regex, probablemente) y/o usar valores flotantes.

Puede que no sea muy eficiente, pero incluso con eso es bastante útil.

Y, uhm, se puede utilizar como clave = para ordenado() también.

0

Hay un buen HOWTO de clasificación en el sitio web de python: http://wiki.python.org/moin/HowTo/Sorting. Hace una buena introducción a la clasificación, y analiza diferentes técnicas para adaptar el resultado de clasificación a sus necesidades.

Cuestiones relacionadas