2009-06-20 13 views
14

Al estar acostumbrado a la forma estándar de ordenar cadenas, me sorprendí cuando noté que Windows ordena los archivos por sus nombres de una manera avanzada. Déjeme darle un ejemplo:Ordenando cadenas que contienen números de una manera fácil de usar

track1.mp3
Track2.mp3
Track10.mp3
Track20.mp3

Creo que esos nombres se comparan (durante la clasificación) basado en las cartas y por números por separado.

Por otro lado, la siguiente es la misma lista ordenada de una manera estándar:
track1.mp3
Track10.mp3
Track2.mp3
Track20.mp3

me gustaría crear un alogoritmo de comparación en Delphi que me permita ordenar cadenas de la misma manera. Al principio pensé que sería suficiente comparar caracteres consecutivos de dos cadenas mientras son letras. Cuando se encuentre un dígito en alguna posición de ambas cuerdas, leeré todos los dígitos que las siguen para formar un número y luego compararé los números.

Para dar un ejemplo, voy a comparar "Track10" y "cadenas" Track2 esta manera:
1) leer los caracteres, mientras que son iguales y mientras que son las letras: "Track", "pista"
2) si se encuentra un dígito, lea todos los dígitos siguientes: "10", "2"
2a) si son iguales, vaya a 1 o termine
Diez es mayor que dos, por lo que "Track10" es mayor que "Track2"

Parecía que todo estaría bien hasta que noté, durante mis pruebas, que Windows consideraba "Track010" menor que "Track10", mientras que yo pensaba que el primero era g Reater porque era más largo (sin mencionar que según mi algoritmo, ambas cadenas serían iguales, lo cual es incorrecto).

¿Podría darme la idea de cómo exactamente Windows clasifica archivos por nombre o tal vez tiene un algoritmo listo para usar (en cualquier lenguaje de programación) en el que pueda basarme?

¡Muchas gracias!
Mariusz

+1

Dupe de muchas otras preguntas, incluyendo: http://stackoverflow.com/questions/34518/natural-sorting-algorithm –

+2

Lo siento, pero ni siquiera sabía qué frase buscar antes. Esta es la razón por la que he duplicado esta pregunta involuntariamente. Ahora sé que esta forma de clasificación se denomina "clasificación natural", por lo que puedo buscar más información sobre esto solo. –

+0

Mira esto http://stackoverflow.com/questions/31538293/sorting-listfileinfo-in-natural-sorted-order –

Respuesta

17

Jeff escribió un artículo sobre esto en Coding Horror. Esto se llama natural sorting, donde trata efectivamente un grupo de dígitos como un solo "carácter". Existen implementaciones en todos los idiomas bajo el sol, pero curiosamente no está incorporado en la mayoría de las bibliotecas estándar de los idiomas.

+4

Gracias por la pista. Me las arreglé para encontrar una función de API de Windows StrCmpLogicalW (http://msdn.microsoft.com/en-us/library/bb759947.aspx) que es lo que estaba buscando. –

+0

Aquí está la implementación de PHP: [natsort] (http://php.net/manual/en/function.natsort.php) –

0

La madre de todas las clases:

ls '*.mp3' | sort --version-sort

1

La absoluta manera más fácil, me encontré, era aislar la cadena que desea, por lo en el caso del OP, Path.GetFileNameWithoutExtension(), elimina los non-digits, convierte a int y ordena. Usando LINQ y algunos métodos de extensión, es un juego de una sola línea.En mi caso, me iba de directorios:

Directory.GetDirectories(@"a:\b\c").OrderBy(x => x.RemoveNonDigits().ToIntOrZero()) 

Dónde RemoveNonDigits y ToIntOrZero métodos son extensiones:

public static string RemoveNonDigits(this string value) { 
    return Regex.Replace(value, "[^0-9]", string.Empty); 
} 

public static int ToIntOrZero(this string toConvert) { 
    try { 
     if (toConvert == null || toConvert.Trim() == string.Empty) return 0;    
     return int.Parse(toConvert); 
    } catch (Exception) { 
     return 0; 
    } 
} 

Los métodos de extensión son herramientas comunes que utilizo en todas partes. YMMV.

+0

Muy buena solución. ¡Trabajó para mi! ¡Gracias! – Pedro77

Cuestiones relacionadas