2009-05-05 10 views
1

linqを使用してリスト内の次のアクティブな項目を探したい場合に問題があります。次に、次のアクティブな項目は、startDateとEndDateによって定義されます。ここに例のリストがあります。LINQを使用してリスト内の次のアクティブな項目を取得する方法

//-- Create Lists of turns  
    IList<Turn> turns= new List<Turn>(){ 
       new Turn(){Name = "Turn 1", StartDate = DateTime.Parse("2009-05-01"), EndDate = DateTime.Parse("2009-05-01") } 
     ,  new Turn(){Name = "Turn 2", StartDate = DateTime.Parse("2009-06-01"), EndDate = DateTime.Parse("2009-06-01") } 
     ,  new Turn(){Name = "Turn 3", StartDate = DateTime.Parse("2009-07-01"), EndDate = DateTime.Parse("2009-07-02") } 
     ,  new Turn(){Name = "Turn 4", StartDate = DateTime.Parse("2009-08-01"), EndDate = DateTime.Parse("2009-08-03") } 
    } 

//-- Get the next Turn by DateTime. 
DateTime toDay = DateTime.Parse("2009-06-02"); 

//-- Should return the "Turn 3" item... 
Turn turn = (from item in turns 
      where ..... 
      select turn).FirstOrDefault<Turn>(); 

TurnでstartDate/endDateプロパティを使用して次のターンを見つける良い方法はありますか?私はstartdateでリストを最初に注文し、リストの最初のものを見つけようとしましたが、もっと正しい "ターン"を見つけるためにリストを必要としないようにもっと安全な方法があれば尋ねます。

+0

私は解決策を提案しましたが、適切なターンを選択する条件についてより具体的に説明できますか? – Noldorin

答えて

0

今日の後に開始日が付いた最初のアイテムを取得してみませんか?私はリストがソートされていることを確認するために、OrderBy()という呼称を追加しました。それがソートされていることが分かっているなら、もちろんそれを残すことができます。

turns.OrderBy(t => t.StartDate).FirstOrDefault(t => t.StartDate > today); 

UPDATE

私はあなたの最後の行を逃しました。はい、あなたはリストを明示的にソートせずにそれを行うことができます。今日の後の開始日を持つ項目のリストを検索しなければならず、今日の後で現在の項目の開始日より前の開始日を持つ項目でなければなりません。しかし、これは事物O(n²)を作っている全てのアイテムについてリスト全体を見なければならないので、検索を本当に遅くするでしょう。

turns.Single(t => 
    t.StartDate > today && 
    turns.All(u => u.StartDate <= today || u.StartDate > t.StartDate)) 

これは、ターンがオーバーラップしていないことを前提としています。重複している場合は、Singleの代わりにFirstを使用するか、追加の制約を追加して一意の結果を得る必要があります。 最後に、ソートソリューションを使用してください。このソリューションは、ソートして最初のアイテムを取得するより安全です。

+0

私は最後の声明を試みましたが、それは非常に遅かった、私は最初にリストをソートし、FirstOrDefaultを取得する必要があると思います... 私が望むものを活かすための最も簡単な方法のようです... –

0

私はあなただけしたいと思う:

var turn = turns.SkipWhile(t => t.EndDate < today).FirstOrDefault(); 

はこれが含むか、あなたが探しているように見えるものを指定した日付today、後のいずれかに最初のターンを返します。もちろん、あなたのturnsリストはすでにソートされているものとします。

編集:私はあなたがリストを並べ替えることを望んでいないことについて少し迷っています。私はあなたが適切なターンを選択するのに必要な条件についてまだ完全にはわかっていないので、クエリを改善することができます。

+0

リストがソートされていない場合、これは失敗する可能性があります。今日の後の最初の項目を返すだけですが、今日の後の最初の項目は必ずしも返す必要はありません。 –

+0

@ダニエル:そうです。しかし、この質問の例は、彼のリストが既にソートされていることを示しているので、私は本当にそれに応答していました。彼はとにかくそれを整理すると述べたので、彼は明らかに問題を認識しています。それにもかかわらず、私は注意書きを追加します。 – Noldorin

+0

あなたは私がしたのと同じ間違いをしました。質問の最後の行を忘れました。彼は次のアイテムを手に入れる方法を探していますが、ソートアルゴリズムを信頼していないようですので、リストを最初にソートすることはありません。 –

1

これは可能です。

Turn turn = turns 
    .Where(t => t.StartDate >= toDay) 
    .OrderBy(t => t.StartDate) 
    .FirstOrDefault(); 

Whereコールはオプションです。その目的は、注文する必要があるアイテムの量を減らすことです。

+0

コールすると、実際には動作しません。私はそれが2つの目的を果たしていることを意味していると思います。少なくとも、OrderByコールの前に配置する方が効率的です。 – Noldorin

+0

良い点。 –

関連する問題