2012-02-20 15 views
13

tengo lista como estaCadena problema de clasificación en C#

List<string> items = new List<string>(); 
    items.Add("-"); 
    items.Add("."); 
    items.Add("a-"); 
    items.Add("a."); 
    items.Add("a-a"); 
    items.Add("a.a"); 

    items.Sort(); 

    string output = string.Empty; 
    foreach (string s in items) 
    { 
     output += s + Environment.NewLine; 
    } 

MessageBox.Show(output); 

La salida está volviendo tan

- 
. 
a- 
a. 
a.a 
a-a 

donde como estoy esperando los resultados como

- 
. 
a- 
a. 
a-a 
a.a 

Cualquier idea por qué "aa" no viene antes de "aa" donde "a-" viene antes que "a".

Respuesta

4

Si desea que su cadena de clasificación de se basará en el valor del byte real en oposición a las reglas definidas por la cultura actual que puede ordenar por Ordinal:

items.Sort(StringComparer.Ordinal);

Esto hará que los resultados sean consistentes en todas las culturas (pero producirá clasificaciones poco intuitivas de "14" antes de "9" que pueden ser o no lo que está buscando).

+0

Gracias Jared, ¿podría decirme cómo puedo ordenar si los datos están en una columna de DataTable? DataTable dataTable = new DataTable(); dataTable.Columns.Add ("Item", typeof (string)); dataRow = dataTable.NewRow(); dataRow ["Item"] = "a-a"; dataTable.Rows.Add (dataRow); dataRow = dataTable.NewRow(); dataRow ["Item"] = "a.a"; dataTable.Rows.Add (dataRow); DataRow [] rows = dataTable.Select ("", "Item ASC"); ' – Satya

4

El método de la clase List<>Sort se basa en el comparador predeterminado string de .NET Framework, que es en realidad una instancia de la corriente CultureInfo del Thread.

El CultureInfo especifica el orden alfabético de los caracteres y parece que el predeterminado utiliza una orden diferente a la que cabría esperar.

Cuando la clasificación se puede especificar un determinado CultureInfo, uno que sabe que coincida con sus requisitos de clasificación, la muestra (cultura alemana):

var sortCulture = new CultureInfo("de-DE"); 
items.Sort(sortCulture); 

Más información se puede encontrar aquí:
http://msdn.microsoft.com/en-us/library/b0zbh7b6.aspx
http://msdn.microsoft.com/de-de/library/system.stringcomparer.aspx

+0

Lo que no está claro es "-" (guión) viene antes de "." (Punto) y "a-" antes de "a"; ¿por qué no 'aa' antes de 'aa'? – Satya

+0

Teóricamente, la cultura actual podría considerar '.' y' -' como el mismo orden. El método '.Sort' es" inestable ", lo que significa que el orden de elementos iguales no está garantizado. –

+1

Probé en inglés de EE. UU. y obtuve los mismos resultados que el OP. Incluso cuando realicé la prueba con String.Compare, nunca obtuve 0 (igual). Obtuve -1 o 1, dependiendo de cuál fue el primero. probablemente no sea un problema con el método .Sort. –

15

Sospecho que en el último caso "-" se trata de una manera diferente debido a la configuración específica de la cultura (tal vez como un "guión" en lugar de "menos" en las primeras cadenas). MSDN warns en esto:

La comparación utiliza la cultura actual para obtener específico de la cultura información, como reglas carcasa y el orden alfabético de caracteres individuales. Por ejemplo, una cultura podría especificar que ciertas combinaciones de caracteres sean tratadas como un solo carácter, o mayúsculas y minúsculas comparadas de una manera particular, o que el orden de clasificación de un carácter dependa de los caracteres que preceden o Siguelo.

también vemos en this MSDN page:

El .NET Framework utiliza tres maneras distintas de clasificar: ordenar palabras, cadena de ordenar y ordenar ordinal. El tipo de palabra realiza una comparación sensible a la cultura de las cadenas. Ciertos caracteres no alfanuméricos pueden tener pesos especiales asignados a ellos; por ejemplo, el guión ("-") podría tener asignarle un peso muy pequeño para que "cooperativa" y "cooperativa" aparezcan juntas en una lista ordenada. El tipo de secuencia es similar al tipo de palabra , excepto que no hay casos especiales; por lo tanto, todos los símbolos no alfanuméricos aparecen antes que todos los caracteres alfanuméricos. La clasificación ordinal compara cadenas basadas en los valores Unicode de cada elemento de la cadena.

Por lo tanto, el guión recibe un tratamiento especial en el modo de ordenamiento predeterminado para que la palabra se ordene más "natural".

Usted puede obtener "normal" tipo ordinal si a su vez específicamente en:

 Console.WriteLine(string.Compare("a.", "a-"));     //1 
    Console.WriteLine(string.Compare("a.a", "a-a"));    //-1 

    Console.WriteLine(string.Compare("a.", "a-", StringComparison.Ordinal)); //1 
    Console.WriteLine(string.Compare("a.a", "a-a", StringComparison.Ordinal)); //1 

para ordenar la colección original usando ordinal utilización de comparación:

 items.Sort(StringComparer.Ordinal); 
+0

Creo que lo has descifrado, el tipo de palabra parece ser el problema aquí. – ntziolis

+0

@ntziolis: Parece que esta es la c ase de hecho –

+0

cómo especificar este comparador ordinario si los datos están en DataColumn de una DataTable – Satya