2010-03-30 12 views
18

Me gustaría saber si hay algo similar a la función PHP natsort en Python?Python analog de la función natsort (ordenar una lista usando un algoritmo de "orden natural")

l = ['image1.jpg', 'image15.jpg', 'image12.jpg', 'image3.jpg'] 
l.sort() 

da:

['image1.jpg', 'image12.jpg', 'image15.jpg', 'image3.jpg'] 

pero me gustaría llegar:

['image1.jpg', 'image3.jpg', 'image12.jpg', 'image15.jpg'] 

ACTUALIZACIÓN

base de Solución de this link

def try_int(s): 
    "Convert to integer if possible." 
    try: return int(s) 
    except: return s 

def natsort_key(s): 
    "Used internally to get a tuple by which s is sorted." 
    import re 
    return map(try_int, re.findall(r'(\d+|\D+)', s)) 

def natcmp(a, b): 
    "Natural string comparison, case sensitive." 
    return cmp(natsort_key(a), natsort_key(b)) 

def natcasecmp(a, b): 
    "Natural string comparison, ignores case." 
    return natcmp(a.lower(), b.lower()) 

l.sort(natcasecmp); 
+3

es 'iamge3' mal escrito intencionalmente? si es así, no veo a quién podría obtener el pedido que desea con ninguna de las herramientas. – SilentGhost

+0

Es un orden natural, image3.jpg está en su lugar –

+2

¿Qué parte de ** mal escrito ** no entiendes? – SilentGhost

Respuesta

37

De my answer-Natural Sorting algorithm:

import re 
def natural_key(string_): 
    """See http://www.codinghorror.com/blog/archives/001018.html""" 
    return [int(s) if s.isdigit() else s for s in re.split(r'(\d+)', string_)] 

Ejemplo:

>>> L = ['image1.jpg', 'image15.jpg', 'image12.jpg', 'image3.jpg'] 
>>> sorted(L) 
['image1.jpg', 'image12.jpg', 'image15.jpg', 'image3.jpg'] 
>>> sorted(L, key=natural_key) 
['image1.jpg', 'image3.jpg', 'image12.jpg', 'image15.jpg'] 

Para apoyar cadenas Unicode, .isdecimal() deben usarse en lugar de .isdigit(). Vea el ejemplo en @phihag's comment. Relacionado: How to reveal Unicodes numeric value property.

.isdigit() también pueden fallar (el valor de retorno no es aceptado por int()) para una cadena de bytes en Python 2 en algunas configuraciones regionales, por ejemplo, '\xb2' ('²') in cp1252 locale on Windows.

+0

@phihag: Funciona en Python 3. – jfs

+1

Vaya, tiene toda la razón. He estropeado el caso de prueba: el error no tiene nada que ver con Python 3. '\ d' y' isdigit' solo coinciden con los valores que 'int' no acepta. [Observe '[u'² '] .sort (clave = tecla_natural)'] (http://ideone.com/iMEmv). – phihag

+0

Advertencia: funciona para el ejemplo específico que se muestra pero falla en casos como ['elm1', 'Elm2'] y ['0.501', '0.55'] y [0.01, 0.1, 1] ... ver http: // stackoverflow .com/questions/4836710/does-python-have-a-built-in-function-for-string-natural-sort/27430141 # 27430141 for lower() y mi solución más general para el orden natural de Python. –

2

Esta función se puede utilizar como argumento para key=sorted en Python 2.xy 3.x:

def sortkey_natural(s): 
    return tuple(int(part) if re.match(r'[0-9]+$', part) else part 
       for part in re.split(r'([0-9]+)', s)) 
+0

'.isdecimal()' es unicodo método solo. No funcionará en cadenas de bytes. '.isdecimal()' coincide con el mismo conjunto de caracteres ([Nd]) que '\ d' que es más grande que' [0-9] 'en el caso Unicode. – jfs

+0

No tengo idea de cuál sería la semántica de ordenar cadenas de dos bytes, así que no lo consideré. Pero tienes razón, la prueba es defectuosa. Cambiado a 're.match'. – phihag

+0

+1. No utiliza [clasificación Unicode adecuada] (http://www.unicode.org/reports/tr10/) por lo que no veo por qué rechazaría cadenas de bytes. Por cierto, los nombres de archivo * nix son solo bytes. No desea que 'ls' se rompa solo porque hay un nombre de archivo gracioso en un directorio. – jfs

12

Se puede extraer de la biblioteca de terceros natsort en PyPI:

>>> import natsort 
>>> l = ['image1.jpg', 'image15.jpg', 'image12.jpg', 'image3.jpg'] 
>>> natsort.natsorted(l) 
['image1.jpg', 'image3.jpg', 'image12.jpg', 'image15.jpg'] 

Descripción completa, soy el autor.

+0

Quería usarlo, pero no lo encontré para Python 3.5 – FiReTiTi

+0

@FiReTiTi Es compatible tanto con python 2 como con python 3. Tengo curiosidad por saber cómo concluyó que no está disponible para Python 3. – SethMMorton

+0

Intenté Úselo y natsort no estaba disponible. Así que le pedí a MacPort que lo instalara, pero quería forzarme a instalar Python 3.4 o 2.7 junto con natsort, que no quiero porque Python 3.5 ya está instalado. – FiReTiTi

Cuestiones relacionadas