2012-02-20 12 views
13

ho lista come questaString problema di ordinamento in 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); 

L'uscita sta tornando come

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

dove, come mi aspetto i risultati come

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

Qualsiasi idea perché "aa" non viene prima di "aa", dove "a-" viene prima di "a".

risposta

4

Se volete che il vostro stringa di sorta per essere basato sul valore del byte effettivo in contrapposizione alle regole definite dalla cultura corrente che è possibile ordinare per ordinale:

items.Sort(StringComparer.Ordinal);

Ciò renderà i risultati coerenti in tutte le culture (ma produrrà ordinamenti non intuitivi di "14" prima di "9" che potrebbero o meno essere quelli che stai cercando).

+0

Grazie Jared, potresti dirmi come posso ordinare se i dati sono in una colonna di DataTable 'DataTable dataTable = new DataTable(); dataTable.Columns.Add ("Articolo", typeof (stringa)); dataRow = dataTable.NewRow(); dataRow ["Articolo"] = "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

Il Sort metodo della classe List<> deduce il difetto string di confronto di .NET Framework, che è in realtà un'istanza della corrente CultureInfo del Thread.

Il CultureInfo specifica l'ordine alfabetico dei caratteri e sembra che quello predefinito stia utilizzando un ordine diverso da quello che ci si aspetterebbe.

Quando si ordina è possibile specificare una specifica CultureInfo, uno che si sa sarà soddisfare le vostre esigenze di ordinamento, campione (cultura tedesca):

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

Maggiori informazioni possono essere trovate qui:
http://msdn.microsoft.com/en-us/library/b0zbh7b6.aspx
http://msdn.microsoft.com/de-de/library/system.stringcomparer.aspx

+0

ciò che non è chiaro è "-" (trattino) viene prima di "." (Punto) e "a-" prima di "a"; perché non "aa" prima di "aa"? – Satya

+0

In teoria, la cultura corrente potrebbe considerare '.' e' -' come lo stesso ordine.Il metodo '.Sort' è" unstable ", che significa che l'ordine di elementi uguali non è garantito –

+1

Ho provato l'inglese americano e ho ottenuto gli stessi risultati dell'OP. Anche quando eseguivo il test utilizzando String.Compare, non ho mai ottenuto 0 (uguale). Ho ottenuto -1 o 1, a seconda di quale era il primo. probabilmente non è un problema con il metodo .Sort. –

15

Sospetto che nell'ultimo caso "-" venga trattato in modo diverso a causa di impostazioni specifiche della cultura (forse come un "trattino" in contrapposizione a "meno" nelle prime stringhe). MSDN warns su questi:

Il comparatore utilizza la lingua corrente per ottenere specifici cultura informazioni quali regole involucro e l'ordine alfabetico singoli caratteri. Ad esempio, una cultura potrebbe specificare che alcune combinazioni di caratteri siano trattate come un singolo carattere, o caratteri maiuscoli e minuscoli essere confrontati in un modo particolare, o che l'ordinamento di un carattere dipende dai caratteri che precedono o seguilo.

vedi anche in this MSDN page:

.NET Framework utilizza tre modi distinti di cernita: ordinamento di parola, stringa di ordinamento e ordinamento ordinale. Ordinamento di parole esegue un confronto di stringhe con la lingua sensibile . Alcuni caratteri non alfanumerici possono avere pesi speciali assegnati a ; ad esempio, il trattino ("-") potrebbe assegnargli un peso molto ridotto in modo che "coop" e "co-op" vengano visualizzati uno accanto all'altro in un elenco ordinato. L'ordinamento delle stringhe è simile all'ordinamento delle parole , tranne per il fatto che non ci sono casi speciali; pertanto, tutti i simboli non anfanumerici precedono tutti i caratteri alfanumerici. Ordinamento ordinale confronta le stringhe in base ai valori Unicode di ciascun elemento della stringa.

Quindi, il trattino ottiene un trattamento speciale nella modalità di ordinamento predefinita per rendere la parola più "naturale".

È possibile ottenere "normale" tipo ordinale se specificamente accende:

 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 

per ordinare la raccolta originale utilizzando uso confronto ordinale:

 items.Sort(StringComparer.Ordinal); 
+0

Penso che lo abbiate incrinato, la parola sorta sembra essere il problema qui. – ntziolis

+0

@ntziolis: Sembra che questo sia il c davvero. –

+0

come specificare questo comparatore ordinale se i dati sono in DataColumn di un DataTable – Satya