2011-01-06 22 views
4

私はラムダ式が初めてで、理解できないものに遭遇しました。誰かがこのラムダソート式がうまくいかない理由を教えてもらえますか?

私はそうのようなオブジェクトを持っている:

class MyListItem 
{ 
    string date; //date in the format "2010-12-05" 
    int Hour; //hour of day as an int 

} 

は、私はいくつかの日付と時間を表す、これらのオブジェクトのリストを持っています。

は、私は、日付と時間によって、このリストをソートしたいので、私はこれを試してみてください。

List<MyListItem> myList = new List<MyListItem>(); 

myList = getsomedata(); //populate list 

myList.Sort((a, b) => (a.date + a.Hour.ToString()).CompareTo(b.date + b.Hour.ToString())); 

、それは一種の、動作します。それはそうのようなソート結果として、時には2桁ではありませんので、問題は、時間がintであるということである。

2010-12-05 1 
2010-12-05 10 
2010-12-05 11 
2010-12-05 12 
2010-12-05 13 
2010-12-05 2 
2010-12-05 21 
2010-12-05 22 

私はそれのようになりたい:

2010-12-05 1 
2010-12-05 2 
2010-12-05 10 
2010-12-05 11 
2010-12-05 12 
2010-12-05 13 
2010-12-05 21 
2010-12-05 22 

ので、私はフォーマットしてみてくださいラムダで一緒に解析する前に文字列を0にする:

ret.Sort((a, b) => (a.date + a.Hour.ToString("00")).CompareTo(b.date + b.Hour.ToString("00"))); 

コンパイルされません。それは私に教えてくれる:

Cannot convert lambda expression to type 'Systems.Collections.Generic.IComparer<MyListItem>' because it is not a delegate type. 

Huh?この状況でプレーン.ToString()(フォーマット文字列なし)と.ToString( "00")の違いは何ですか?

また、この方法をどのように取得するかについてのご意見はありますか?

+0

「ret」の種類は何ですか? 'List 'を作成すると、2番目のソートルーチンのコンパイルに問題はありません。再現性のために、どのバージョンのコンパイラとフレームワークを使用していますか? – Ani

+0

コンパイルエラーが発生しないことを不思議です。 retはリスト()です(myList、cut&pasteエラーがあったはずです)。私はvs2010、.net 4.0を使用しています。 – BDW

答えて

0

助けてくれた皆様に感謝します。

class MyListItem 
{ 
    string date; //date in the format "2010-12-05" 
    int? Hour; //hour of day as an int 

} 

私が使用している実際のクラスは、私が与えた例よりもはるかに大きい生成されたクラスがある:それは結局のところ、問題は、元のクラスでは、時間だったようなので、NULL可能であることをしましたここでは、事を明確にするためにそれを短くしようとしたが、関連する部分を残してしまった。 NULL可能int型の値を使用するように並べ替えを変更

作品:

myList.Sort((a, b) => (a.date + a.Hour.Value.ToString("00")).CompareTo(b.date + b.Hour.Value.ToString("00"))); 

エラーメッセージが多くの助けませんでしたが、全員の作業実施例は私がそれを追跡することができました。

2

これは、通常はソートされずに文字列としてソートされているためです。日付を比較するために比較者を作成する必要があります。並べ替えを見てください - 1で始まるものが2で始まるものより先行するので、1、11、111、1111、2、22,222,223,333,333などが得られます。

結果の文字列を日付に変換してください。修正する必要があります。

DateTime.ParseExact(a.date + hour.ToString("00"), "yyyy-MM-dd HH", CultureInfo.InvariantCulture) 

ToString()によって発生した例外に関するコンパイルの問題を回避する必要があります。

+0

これはコンパイルの問題と何が関係していますか? – Ani

+1

@Ani:この答えは、OPの問題を解決するためのより良い方法を示唆していると思います。 – VoodooChild

+1

日付は "そのまま"ソート可能です - "yyyy mm dd"は解析することなくソートすることができます。 OPは*すでに*文字列として有効にソート可能な方法で*時間を処理するための措置をとっている*。* –

5
私は私が最初に説明することはできませんが、私はそれを回避したいPCではないよ

ret.Sort((a,b) => { 
    int result = string.Compare(a.date,b.date); 
    if(result==0) result = a.hour.CompareTo(b.hour); 
    return result; 
}); 

少ない文字列の作成、無構文解析のオーバーヘッドなど;)

1

それ日付がString形式で比較されているからです。

次のようにあなたのラムダコールを変更

ret.Sort((a, b) => (DateTime.Parse(a.date + " " +a.Hour.ToString("00") 
+ ":00:00").CompareTo(DateTime.Parse(b.date + " " + b.Hour.ToString("00") + ":00:00"))); 
+0

そして" yyyy mm dd hh "文字列としてソートする。 –

0

をあなたはクレイジー取得し、既存のフィールドを組み合わせて、日時を返す拡張メソッド作ることができます - そしてちょうどソートその上を。

ロジックはまた、同様にソート式で直接使用することができると言いましたが、その後、あなたは拡張メソッドを使用することを得ることはありません:)

のpublic static DateTimeののGetDate(このMyListItem myListItem) { リターンのDateTimeは。パース(myListItem.date).AddHours(myListItem.Hour); }

2

上記のコードは、フォーマットの有無にかかわらず完全に機能します。私はそのような間違った行動の理由を見ない。

List<MyListItem> myList = new List<MyListItem>(); 

     getsomedata(myList); //populate list 

     myList.Sort((a, b) => (a.date + a.Hour.ToString("00")).CompareTo(b.date + b.Hour.ToString("00"))); 

    private void getsomedata(List<MyListItem> items) 
    { 
     for (int i = 1; i < 30; i += 3) 
     { 
      items.Add(new MyListItem("2010-12-05", i)); 
     } 
     for (int i = 2; i < 30; i += 3) 
     { 
      items.Add(new MyListItem("2010-12-05", i)); 
     } 
    } 

    class MyListItem 
    { 
     public MyListItem(string date, int hour) { this.date = date; this.Hour = hour; } 
     public string date; //date in the format "2010-12-05" 
     public int Hour; //hour of day as an int 
    } 
関連する問題