2017-11-19 4 views
-1

Personクラスの両方が含まれているクラスリストソートする:私は、次のようなCSVファイルから文字列データをソートすることができる午前どのようにダブル、文字列データ

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('"')); 

        } 
       } 

      } 
     } 
    } 

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; 
     } 

マイプログラムコードを名前ですが、年齢と身分証明書で正しい注文(昇順または降順)を取得できません 私はこの問題について多くのことを検索しました。 IcomparableおよびTryparse を使用しようとしましたが、肯定的な結果はありません。問題は、Orderbyが年齢とIDを文字列として処理することです。しかし、AgeとIDをdoubleまたはintと定義すると、temp配列を定義しているときに "変換できません"ということになります。任意の有益な提案や解決をお願いします。

これは、たとえば年齢に従って注文した場合に発生します。それはまだIDによると発注しているようだ!代わりに、式の 1

+1

コードの壁は読みにくい(特に、垂直方向の間隔が広すぎる)。あなたの問題を示す*最小の例に減らしてください。 – Richard

+0

複数の新しいリストを作成してから、それらのリストに割り当てる必要はありません。 'var personList_name =新しいリスト(); personList_name = personList.OrderBy(...); '不必要に新しいリストを割り当てて、そこに2番目の行を上書きします。また、 'TryParse'を含む' OrderBy'は 'true' /' false'メソッドの結果で順序付けされ、解析された値ではありません。彼らが正常に解析すると、それらは 'true'によって順序付けられます。解析に失敗したものは 'false'によって順序付けられます。 (昇順)順序では、 'false'は' true'の前に来ます。その後、結果はおそらく(?)ランダムです。 – pinkfloydx33

答えて

0

、機能提供:

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

それとも拡張メソッド書き込みきれいなものを維持するために:

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

をそして、このように呼び出す:

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

ありがとう!それは適切に働いた。このような並べ替えにWindowsフォームアプリケーションを使用する方が良いでしょうか? – utdlegend

+0

ASP.NETとWindowsフォームは並べ替えとは関係ありません。 –

0

試しました

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

?それがint値

+0

Okey John Wuの答えがより安全であるようです... –

+0

これは、このエラーをcmd画面の "未処理の例外入力文字列が正しい形式ではありませんでした" – utdlegend

0

問題はTryParseboolなく解析された値を返すことであることによって、それらを並べ替える必要があります

この方法です。 OrderByとなります。truefalseの順です。昇順では、falsetrueの前にとなります。

これらの値が常に整数であることが期待される場合は、いくつかのオプションがあります。

私の意見では、クラスのプロパティを整数に変更し、コンストラクタで解析を行い、不正な値が渡された場合に例外をスローします(無効なPersonが作成されないようにする)。

OrderBy内のint.Parseに切り替えることです。これは、例外がスローされるため、すべての値を確実に解析できる場合にのみ機能します。あなたが選んだのしたいことがあり

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

あなたがTryParseを(例えば、整数データであることを保証いないと、あなたのクラス定義を変更することはできません)を使用する必要がある場合、あなたはマルチステートメントラムダを使用することができますあなたがそれらをソートする場所に応じて、失敗のケースの異なる値。上記の場合、すべての失敗が最初に起こりますが、で、IDは負ではないと仮定しています。代わりにint.MinValueを使用できます。あなたが最後に来るようにしたい場合は、int.MaxValueを使うことができます。もしあなたのIDが正当にそれほど大きければ問題はあります(私は少なくとも誰もがageを持っていると思います)。

もう1つの方法は、最初にSelectを使用して、必要なデータを含む匿名型を作成することで失敗を除外することです(該当する場合は正しく解析し、元のPerson)。次に、Whereを使用して、解析に失敗した値をフィルタリングし、次に解析されたデータに対してOrderByをフィルタします。最後に別のSelectを使用して、Personを匿名タイプから抽出します。

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); 
関連する問題