2017-11-19 3 views
-1

Person-Klasse beide Doppel-und String-Daten enthalten:Wie eine Klassenliste sortieren, die

class Person 
    { 
     public string ID; 
     public string Name; 
     public string PClass; 
     public string Age; 
     public string Sex; 
     public string Survived; 
     public string SexCode; 
     public Person(string id,string name,string pclass,string age,string sex, 
      string survived,string sexcode) 
     { 
      ID = id; 
      Name = name; 
      PClass = pclass; 
      Age = age; 
      Sex = sex; 
      Survived = survived; 
      SexCode = sexcode; 
     } 

Mein Programmcode:

class Program 
    { 
     static void Main(string[] args) 
     { 


      string[] data = File.ReadAllLines("titanic.csv"); 
      data = data.Skip(1).ToArray(); 
      List<Person> personList = new List<Person>(); 
      List<Person> personList_name = new List<Person>(); 
      List<Person> personList_pclass = new List<Person>(); 
      List<Person> personList_age = new List<Person>(); 
      List<Person> personList_sex = new List<Person>(); 
      List<Person> personList_id = new List<Person>(); 

      for (int i = 0; i < data.Length; i++) 
      { 
       string[] temp = Regex.Split(data[i], ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)"); 
       Person person = new Person(temp[0], temp[1], temp[2],temp[3], 
       temp[4], temp[5], temp[6]); 
       personList.Add(person); 

      } 

      personList_name = personList.OrderBy(x => x.Name).ToList(); 
      personList_pclass = personList.OrderBy(z => z.PClass).ToList(); 
      personList_sex = personList.OrderBy(w => w.Sex).ToList(); 
      int id_; 
      int age_; 
      personList_age = personList.OrderBy(y => int.TryParse(y.Age, out age_)).ToList(); 
      //personList_id = personList.OrderByDescending(int.TryParse(ID, out number)).ToList(); 
      personList_id = personList.OrderBy(o => int.TryParse(o.ID, out id_)).ToList(); 

      while (true) 
      { 
       Console.WriteLine(" Please select your filtring method:\n" + 
        "1-By Name\n2-By Pclass\n3-By Age\n4-By Sex\n5-By ID\n Press -1 to quit."); 
       string selection = Console.ReadLine(); 
       if (selection == "-1") 
       { 
        break; 
       } 

         Console.WriteLine(("{0,-10}{1,70}{2,20}{3,20}{4,20}{5,20}{6,20}"), item.ID.Trim('"'), item.Name.Trim('"'), item.PClass.Trim('"') 
          , item.Age, item.Sex.Trim('"'), item.Survived.Trim('"') 
          , item.SexCode.Trim('"')); 
        } 
       } 
       if (selection == "3") 
       { 
        Console.WriteLine(("{0,-10}{1,70}{2,20}{3,20}{4,20}{5,20}{6,20}"), "ID", "NAME", "PCLASS", "AGE", "SEX", "SURVIVED", "SEXCODE"); 
        foreach (var item in personList_age) 
        { 
         Console.WriteLine(("{0,-10}{1,70}{2,20}{3,20}{4,20}{5,20}{6,20}"), item.ID.Trim('"'), item.Name.Trim('"'), item.PClass.Trim('"') 
          , item.Age, item.Sex.Trim('"'), item.Survived.Trim('"') 
          , item.SexCode.Trim('"')); 

        } 
       } 

      } 
     } 
    } 

ich in der Lage bin String-Daten aus einer CSV-Datei zu sortieren, wie Name, aber für Alter und ID kann ich nicht die richtige Reihenfolge (aufsteigend oder absteigend) erhalten Ich habe viel über dieses Problem gesucht. Versucht, Icomparable und Tryparse zu verwenden, aber ohne ein positives Ergebnis. Das Problem ist, dass Orderby mit Alter und ID als String arbeitet. Aber wenn ich Age und ID als Double oder Int definiere, werde ich beim Definieren des Temp-Arrays "nicht konvertieren" können. Jeder hilfreiche Vorschlag oder Lösung BITTE?

Das passiert, wenn ich zB nach Age ordere. Es scheint immer noch nach ID zu bestellen! 1

+1

Die Codewand ist zu schwer zu lesen (besonders bei übermäßigem vertikalem Abstand). Reduziere auf ein * minimales * Beispiel, das dein Problem zeigt. – Richard

+0

Erstellen Sie keine neuen Listen und weisen Sie sie dann über sie zu. 'var personList_name = new Liste (); personList_name = personList.OrderBy (...); 'Ordnen Sie unnötigerweise eine neue Liste zu und überschreiben Sie sie dort mit der zweiten Zeile. Auch Ihre 'OrderBy's mit dem' Tryparse' in ihnen ordnen sich nach dem Ergebnis der Methode an, die 'true' /' false' ist und NICHT den geparsten Wert. Wenn sie erfolgreich parsen, werden sie nach 'true' geordnet; Dinge, die nicht analysiert werden, werden mit 'false' geordnet. In einer (aufsteigenden) Reihenfolge kommt 'falsch 'vor' wahr '. Danach sind die Ergebnisse wahrscheinlich (?) Zufällig. – pinkfloydx33

Antwort

0

Statt eines Ausdrucks, bieten eine Funktion:

personList_age = personList.OrderBy 
(
    y => { 
      int age; 
      bool ok = int.TryParse(y.Age, out age); 
      return ok ? age : default(int); 
     } 
).ToList(); 

Oder Dinge sauber zu halten vielleicht eine Erweiterungsmethode schreiben:

static void int ToInt(this string input) 
{ 
    int n; 
    bool ok = int.TryParse(input, out n); 
    return ok ? n : default(int); 
} 

Und nennen wie folgt aus:

personList_age = personList.OrderBy(y => t.Age.ToInt()); 
+0

Danke! Es hat richtig funktioniert. Ist es besser, Windows-Formularanwendung für diese Art der Sortierung zu verwenden? – utdlegend

+0

ASP.NET vs Windows Forms hat nichts mit Sortieren zu tun. –

0

Haben Sie versucht

personList.OrderBy(x => Convert.ToInt32(x.id)).ToList(); 

?

diese Weise ist es ihnen durch den int-Wert

+0

Okey John Wus Antwort scheint sicherer zu sein ... –

+0

Dies wird dazu führen, dass dieser Fehler in cmd Bildschirm angezeigt wird "unbehandelte Ausnahme Eingabezeichenfolge war nicht in einem korrekten Format" – utdlegend

0

Das Problem ist, dass TryParse gibt einen bool und nicht die analysierte Wert sortieren soll. OrderBy dann Bestellungen true vs false. In aufsteigender Reihenfolge kommt falsevortrue.

Wenn Sie erwarten, dass diese Werte immer ganze Zahlen sind, haben Sie einige Optionen.

Das bessere (meiner Meinung nach) ist, diese Eigenschaften in Ihrer Klasse in Ganzzahlen zu ändern und Ihre Parsing im Konstruktor, eine Ausnahme zu werfen, wenn ein ungültiger Wert übergeben wird (nicht eine ungültige Person zu erstellen).

Die zweite Option wäre, innerhalb der OrderBy zu int.Parse zu wechseln. Dies funktioniert nur, wenn alle Werte eindeutig geparst werden können, da sonst eine Ausnahme ausgelöst wird.

Wenn Sie TryParse verwenden müssen (zum Beispiel ist es nicht ganzzahligen Daten sein garantiert und Sie können nicht Ihre Klassendefinition ändern), können Sie eine Multi-Anweisung Lambda verwenden:

personList.OrderBy(person => { 
    int value; 
    return int.TryParse(person.ID, out value) ? value : -1; 
}); 

Möglicherweise möchten Sie wählen ein anderer Wert für den Fehlerfall, abhängig davon, wo Sie sie sortieren möchten. Im obigen Fall würden alle Fehler zuerst kommen - obwohl annimmt, dass kein ID negativ sein könnte. Sie könnten stattdessen int.MinValue verwenden.Wenn Sie wollen, dass sie zuletzt kommen, könnten Sie int.MaxValue verwenden - obwohl, wenn Ihre ID s recht groß sein könnte, Sie ein Problem haben werden (ich denke, es ist sicher anzunehmen, dass niemand einen age so groß haben wird). Eine andere Möglichkeit wäre, die Fehler herauszufiltern, indem zuerst Select verwendet wird, um einen anonymen Typ zu erstellen, der die Daten enthält, die Sie benötigen (erfolgreich geparst, Wert, falls zutreffend, und Ihr Original Person). Verwenden Sie dann Where, um alle Werte zu filtern, die nicht analysiert wurden, gefolgt von OrderBy für die analysierten Daten. Schließlich verwenden Sie eine andere Select, um Ihre Person aus dem anonymen Typ zu extrahieren.

personList.Select(p => { 
    int value; 
    var ok = int.TryParse(p.ID, out value); 
    return new { Ok = ok, ID = value, Person = p }; 
}) 
.Where(result => result.Ok) 
.OrderBy(result => result.ID) 
.Select(result => result.Person); 
Verwandte Themen