Pregunta

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éjame darte un ejemplo:

Track1.mp3
Track2.mp3
Track10.mp3
Track20.mp3

Creo que esos nombres se comparan (durante la clasificación) según las letras y los números por separado.

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

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

Para darle un ejemplo, compararé " Track10 " y "Track2" cadenas de esta manera:
1) lea los caracteres mientras son iguales y mientras son letras: " Track " ;, " Track "
2) si se encuentra un dígito, lea todos los siguientes dígitos: " 10 " ;, " 2 "
2a) si son iguales, vaya a 1 o termine
Diez es mayor que dos, entonces '' 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 pensé que el primero era mayor ya que era más largo (sin mencionar que, según mi algoritmo, ambas cadenas serían iguales, lo cual está mal).

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

¡Muchas gracias!
Mariusz

¿Fue útil?

Solución

Jeff escribió un artículo sobre esto en Coding Horror. Esto se llama ordenación natural , donde trata eficazmente a un grupo de dígitos como un solo '' carácter ''. Hay implementaciones en todos los idiomas bajo el sol, pero extrañamente no suele estar integrado en la mayoría de las bibliotecas estándar de idiomas.

Otros consejos

La forma más fácil y absoluta que encontré fue aislar la cadena que desea, por lo que en el caso del OP, Path.GetFileNameWithoutExtension (), elimine los no dígitos, conviértalos en int y ordénelos. Usando LINQ y algunos métodos de extensión, es una línea. En mi caso, estaba yendo a directorios:

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

Donde RemoveNonDigits y ToIntOrZero son métodos de 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 uso en todas partes. YMMV.

La madre de todo tipo:

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top