Lista ordenada por longitud pero con la misma longitud en orden alfabético en un paso

Mi lista de cadenas de Python es algo así como x pero lo suficientemente largo:

x = ['aaa','ab','aa','c','a','b','ba']      

Quiero ordenar esta lista como: ['a', 'b', 'c', 'aa', 'ab', 'ba', 'aaa'] e hice lo siguiente en dos pasos:

>>> x.sort()   
>>> x.sort(key=len)      
>>> x
['a', 'b', 'c', 'aa', 'ab', 'ba', 'aaa']   

Pero necesito en un solo paso: también até usando lambda función (tomado ayuda):

>>> x.sort(key=lambda item: (item, len(item)))
>>> x
['a', 'aa', 'aaa', 'ab', 'b', 'ba', 'c']  

Pero no como yo deseaba:

¿Es posible en un solo paso? Satisfaceme.

Mi pitón:

~$ python --version  
Python 2.6.6

preguntado el 31 de diciembre de 12 a las 15:12

Edité el python-2.7 etiqueta para python-2.6 como dices claramente que estás usando 2.6. -

2 Respuestas

Obtuviste el orden de la tupla al revés. Cuando Python ordena tuplas, el primer valor es el principal sort, siendo el segundo el subsort, etc... - su código supone el orden opuesto.

Quiere ordenar por longitud, luego alfabéticamente:

>>> x.sort(key=lambda item: (len(item), item))
>>> x
['a', 'b', 'c', 'aa', 'ab', 'ba', 'aaa']

Editar: como señala DSM en los comentarios, Python ordena las letras primero en mayúsculas y luego en minúsculas. Si no se desea este comportamiento, consulte esta respuesta.

contestado el 23 de mayo de 17 a las 11:05

En realidad, esto no se ordena alfabéticamente debido a problemas de mayúsculas y minúsculas (pero eso se soluciona fácilmente). [Admito que la lista del OP está en minúsculas en este momento.] - DSM

@DSM Estaba emulando el comportamiento del código de trabajo original, supuestamente, podría ser un error que las mayúsculas aparezcan primero, pero ese podría ser el comportamiento deseado, no está claro. - gareth latty

@Lattyware: mi trabajo terminó, y lo entendí. Pero una última duda. ¿Cómo funciona la primera solución de 2 pasos? ¡Ordené por orden alfabético y luego por longitud! Esa es la razón por la que no pude pensar en lo que intentaste ... - grijesh chauhan

Su primera solución funciona porque cuando Python ordena una clave y los valores son iguales, realiza una ordenación estable, es decir, el orden de los valores iguales es el orden en que estaban en la entrada. Esto significa que si ordena por un valor, luego por otro, el primer orden cae a través como subclase. - gareth latty

@Lattyware Leí tantas veces en el libro de python este trimestre stable sort pero hoy entendí el significado. Gracias. Ahora lo entendí por completo. - grijesh chauhan

usar itertools.grouby():

In [29]: lis = ['aaa','ab','aa','c','a','b','ba']
In [30]: list(chain(*[sorted(g) for k,g in groupby(sorted(lis,key=len),key=len)]))
Out[30]: ['a', 'b', 'c', 'aa', 'ab', 'ba', 'aaa']

timeit comparaciones:

In [38]: x = ['aaa','ab','aa','c','a','b','ba']*1000

In [39]: random.shuffle(x)

#may be in more tricky test cases this would be fast

In [40]: %timeit sorted(x,key=lambda item: (len(item), item))
100 loops, best of 3: 11.3 ms per loop

In [41]: %timeit list(chain(*[sorted(g) for k,g in groupby(sorted(x,key=len),key=len)]))
100 loops, best of 3: 7.82 ms per loop

Respondido el 31 de diciembre de 12 a las 16:12

Esto parece enormemente complicado. No está mal, pero... Realmente no veo el valor de ello. - gareth latty

Me gusta itertools tanto como el siguiente chico, ¡pero esto es una locura! PD: no necesitas el list llamada, sorted consumirá g y producir una lista. - DSM

@DSM Olvidé eliminar el list() call, lo estaba usando con fines de prueba. Sé que es una forma extraña en comparación con la respuesta de lattyware, pero en cuanto al rendimiento, esto fue más rápido. - Ashwini Chaudhary

@GrijeshChauhan me alegro de que haya ayudado. - Ashwini Chaudhary

@AshwiniChaudhary buena simulación... esta aptitud es muy buena y necesaria... ¡gracias de nuevo! - grijesh chauhan

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.