2016-06-27 2 views
0

Ich habe diese TextBoxes markiert als tb_class# und # = 1-10Sorting Liste <TextBox> Numerisch C#

Bisher ist dies die Funktion I

private List<TextBox> GetCustomClasses() 
    { 
     List<TextBox> tb = new List<TextBox>(); 
     foreach (Control con in gb_customClasses.Controls) 
      if (con.Name.Contains("tb_class")) 
       tb.Add(con as TextBox); 
     return tb.OrderByDescending(x => x.Name.Replace("tb_class", "")).ToList(); 
    } 

Die Ausgabe sieht wie folgt aus:

9 
8 
7 
6 
5 
4 
3 
2 
10 
1 

I könnte einen Scheck dafür hinzufügen, aber ich möchte, dass es in perfekter Reihenfolge läuft. Für diejenigen, die sich fragen gb_customClasses ist ein groupbox.

Gelöst! Schlusscode:

private List<TextBox> GetCustomClasses() 
    { 
     List<TextBox> tb = new List<TextBox>(); 
     foreach (Control con in gb_customClasses.Controls) 
      if (con.Name.Contains("tb_class")) 
       tb.Add(con as TextBox); 
     return tb.OrderByDescending(x => int.Parse(x.Name.Replace("tb_class", ""))).ToList(); 
    } 

Ich glaube nicht einmal über das Hinzufügen von int.Parse

+0

Bitte zeigen Sie die Daten vor dem Ersetzen. Anscheinend haben Sie lexikografisch auf Strings sortiert, nicht auf einem numerischen Typ. – Codor

+3

Es ist einfach genug - Sie verarbeiten die Namen der Steuerelemente, die Strings sind. Wenn Sie alphabetisch bestellen, sind sie in Ordnung! Sie müssen sie als numerischen Typ vergleichen, damit sie in der von Ihnen gewünschten Reihenfolge angezeigt wird. – Bridge

+0

Sie können natürliche Sortierreihenfolge für diese Art von Sache verwenden - [siehe meine Antwort hier] (http://stackoverflow.com/a/31538443/106159) und [diese Antwort hier] (http: // stackoverflow. com/a/248613/106159). –

Antwort

2

Sie müssen eine numerische Sortierung machen, anstatt lexicographic. Versuchen Sie folgendes:

return tb.OrderByDescending(x => int.Parse(x.Name.Replace("tb_class", ""))).ToList(); 

Hinweis, könnten Sie nicht .ToList() nennen müssen, je nach Fall. Ein IEnumerable<TextBox> könnte stattdessen nützlich sein - also überprüfen Sie es.


Haben Sie keine Angst, nicht die Tag Eigenschaft verwenden einige zusätzliche Informationen über Ihre Kontrollen zu speichern! Diese Lösung ist etwas schöner:

return tb.OrderByDescending(x => (int)x.Tag); 

oder

return tb.OrderByDescending(x => ((MyClass)x.Tag).Index); 

Sie müssen nur sicherstellen, dass Sie eine entsprechende Tag für jede TextBox Sie gb_customClasses.Controls hinzufügen. Ich würde zu diesem Ansatz ist in der Regel, wenn der Steuerelemente dynamisch erstellt wird (dann ist Tagging einfach und Benennung nicht einmal ein Muss)

0

Sie Sortierung alphabetisch sie, um Ihre Rückkehr Anweisung ändern:

return tb.OrderByDescending(x => Int32.Parse(x.Name.Replace("tb_class", ""))).ToList(); 

In um die Liste zu erhalten numerisch

3

Sie müssen wandeln es in ein int, hier ist ein LINQ nur Ansatz sortiert:

private List<TextBox> GetCustomClasses() 
{ 
    return gb_customClasses.Controls.OfType<TextBox>() 
     .Where(txt => txt.Name.StartsWith("tb_class")) 
     .OrderByDescending(txt => int.Parse(txt.Name.Substring("tb_class".Length))) 
     .ToList(); 
} 
0

Sie sollten sie als Zahlen werden verglichen, und nicht Strings:

return tb.OrderByDescending(x => Convert.ToInt32(x.Name.Replace("tb_class", ""))).ToList(); 

Hinzufügen ein bisschen den Namen umwandelt, wo Sie die tb_class aus einem String in einen int entfernt.

0

zu

OrderByDescending (x => Convert.ToInt32 (x.Name ändern.Ersetzen ("tb_class", "")))

-2

Dies könnte funktionieren:

private List<TextBox> GetCustomClasses() 
{ 
    List<TextBox> tb = new List<TextBox>(); 

    List<String> indexes = new List<string>(); 

    // N.B. A more conservative implementation might want to go for an unsigned 
    // 64-bit thing here. Just in case you run into a really big GroupBox. 
    // 
    // **WARNING** Due to Brexit, UK compilers will be changing to base 12, which 
    // may adversely affect the performance of this loop. Also keep an eye out for 
    // unpredictable fluctuations in the exchange rate with UK integers. 

    for (String i = "0"; Int32.Parse(i) < 0x7fffffff; i = (Int32.Parse(i) + 1).ToString()) 
    { 
     indexes = indexes.Union(new string[] { i }).ToList(); 
    } 

    var arrayOfIndexes = indexes.ToArray(); 

    // Leave room for null terminator 
    var reordered = new TextBox[gb_customClasses.Controls.Count + 1]; 

    foreach (Control con in gb_customClasses.Controls) 
     if (con.Name.Contains("tb_class")) 
      reordered[arrayOfIndexes.ToList().IndexOf(con.Name.Replace("tb_class", ""))] = con as TextBox; 

    return reordered.ToList(); 
} 
+0

Notoriously unnötige complextion – SimpleVar

+0

@SimpleVar Sollte ich "Indizes" unsigned gemacht haben? –

+0

Nicht sicher, ob Troll ..? Zumindest sollten Sie wissen, dass 'List ' hat eine 'Add' Methode, anstatt' .Union(). ToList() ' – SimpleVar

0

Ich habe diese Textfelder, die als "tb_class #" und # = 1-10

Mit einer solchen Kodierung können Sie die Tatsache nutzen, dass Zahlen mit mehr Ziffern größer sind, und auch LINQ sort ist stabil. Mit anderen Worten, bestellen Sie zuerst zuerst nach der Textlänge, dann nach dem Text:

return tb.OrderByDescending(x => x.Name.Length).ThenByDescending(x => x.Name).ToList();