2012-02-29 8 views
5

に基づいてオブジェクトの一覧から選択:LINQ:グループ化することで、私は以下のように3つのプロパティを持つMYITEMクラスを持っている最大値

var myItems = new List<MyItem>() { 
    new MyItem("A", 123, "23/02/2012"), 
    new MyItem("A", 323, "22/02/2012"), 
    new MyItem("B", 432, "23/02/2012"), 
    new MyItem("B", 356, "22/02/2012"), 
    // ... 
} 
:また

class MyItem 
{ 
    private string _name; 
    private int _value 
    private DateTime _TimeStamp; 

    public MyItem(string name, int value, string timeStamp) 
    { 
     this._name = name; 
     this._value = value; 
     this._timeStamp = DateTime.Parse(timeStamp); 
    } 

    public string Name 
    { get {return this_name; } } 

    public int Value 
    { get {return this._value; } } 

    public DateTime TimeStamp 
    { get {return this._timeStamp; } } 

    // ... 
} 

私は以下のようにMYITEMのリストを持っています

私はどのように私は最大タイムスタンプを持つ項目だけ残っているようにmyListによってGROUP BYできますか?次の結果:

"A" 123 23/02/2012<br> 

"B" 432 23/02/2012<br> 

ありがとうございます。

+0

私はあなたのコードを編集する自由を取った、私はあなたの例を台無しにしていないことを願って – BlackBear

答えて

6
myItems.GroupBy(item => item.Name) 
     .Select(grp => grp.Aggregate((max, cur) => 
          (max == null || cur.Date > max.Date) ? cur : max)) 

これは、新しいオブジェクトを作成し、繰り返し処理を行うことなく、最速の時間で、あなたの結果を(少なくとも私には理解できている)を選択します最も少ない時間を収集する。サンプルコンソールプログラムでは

public MyItem() { }

+0

まさに私が必要としたもの。一致する日付と異なる値を持つデータベースから取得したレコードであっても、最高の価値を取りたいと思っていました。あなたは人に感謝します。 –

0
var tmp = select i from myItems 
group i by i.Name into g 
select new MyItem 
{ 
    g.Name, 
    Value = g.OrderByDescending(x => x.Timestamp).First().Value, 
    Timestamp = g.Max(x => x.Timestamp) 
}; 
+0

これは仲間をコンパイルしません。 – MaYaN

+0

私は "into g"を忘れました。あなたが使用したい場合は、linqを学ぶ必要があります。 –

3

グループからの最大の選択:

from item in MyItems 
group item by item.Name into grouped 
let maxTimeStamp = grouped.Max(i => i.TimeStamp) 
select grouped.First(i => i.TimeStamp == maxTimeStamp) 
+0

@ ALIR.Bousari - あなたは正しいですか?クエリのselectステートメントは* new * 'MyItem'を作成し、[オブジェクト初期化子](http://msdn.microsoft.com/en-us/library/bb397680.aspx)を使用してプロパティを設定しています。 –

+0

@ChristopherCurrens - tnxしかし、上記の私の最近の編集からわかるように、私のプロパティはゲッターだけなので、ここで設定することはできません。本当に新しいオブジェクトを作成したくありません。 – MaYaN

+0

@ ALIR.Bousari - そうだね。さて、私は私の答えを元に戻すでしょう。これらを削除した理由はこれよりも複雑ですが、新しいオブジェクトは作成されません。 –

1
var temp = myItems.Where(x => x.TimeStamp == myItems.Where(y => y.Name == x.Name).Max(z => z.TimeStamp)).Distinct().ToList(); 
+0

すばらしい!ちょうど私が欲しいもの。 – MaYaN

+1

@ ALIR.Bousari - この答えはあなたが期待する出力を生成しますが、それは非常に遅いアルゴリズムです:O(n^2)。私は実行速度を@ JoeTuskanの答えと比較しました。リスト内の* 1000 *項目だけがクエリを5回実行しました。この回答は「00:00:15.8860736」で、ジョーは「00:00:00.0080155」のみでした。 –

+0

@ Christopher、私がSELECTセクション – MaYaN

0

OK、私はクラスに空のコンストラクタを追加することによって、(希望これは問題は発生しません)いくつかのLINQの便宜のために、あなたのクラスMyItemを変更しました

static void Main(string[] args) 
{ 
    var myItems = new List<MyItem>() 
    { 
     new MyItem("A", 123, "23/02/2012"), 
     new MyItem("A", 323, "22/02/2012"), 
     new MyItem("B", 432, "23/02/2012"), 
     new MyItem("B", 356, "22/02/2012") 
     // ... 
    }; 

    var grouped = from m in myItems 
        group m by m.Name into g 
        let maxTimestamp = g.Max(t => t.TimeStamp) 
        select new MyItem 
        { 
         Name = g.Key, 
         Value = g.First(f => f.TimeStamp == maxTimestamp).Value, 
         TimeStamp = maxTimestamp 
        }; 
    foreach (var gItem in grouped) 
    { 
     Console.WriteLine(gItem.Name + ", " + gItem.Value + ", " + gItem.TimeStamp); 
    } 

    Console.ReadLine(); 
} 

出力が期待どおりの結果になります。

関連する問題