2017-07-02 7 views
1

Dictionary<DateTime, int>からデータをフィルタリングして、後続のDateTime'sの差が1分以上の要素のみを取得する必要があります。c#linq filter Dictionary <DateTime、int>定義済みの最小時間差で

例えば、辞書に私はこのようなデータのペアかもしれない:

var pairs = new Dictionary<DateTime, int>() 
{ 
    { new DateTime(2010, 01, 20, 19, 05, 00), 10 }, 
    { new DateTime(2010, 01, 20, 19, 05, 19), 11 }, 
    { new DateTime(2010, 01, 20, 19, 05, 49), 12 }, 
    { new DateTime(2010, 01, 20, 19, 06, 05), 13 }, 
    { new DateTime(2010, 01, 20, 19, 07, 05), 14 }, 
    { new DateTime(2010, 01, 20, 19, 07, 55), 15 }, 
}; 

そして、私はフィルタリングの結果として、希望はある:辞書に

<2010-01-20 19:05:00, 10> 
<2010-01-20 19:06:05, 13> 
<2010-01-20 19:07:05, 14>` 

DateTimeキーが上昇しています注文する必要はありませんが、多くのデータが処理されるため、かなり効率的である必要があります。

私にLINQクエリの素敵な部分を紹介してもらえますか?

+2

を '辞書内のDateTimeキーは昇順です。ドキュメントによれば、「アイテムが返される順序は未定義です。」(https://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspx)。それは今日働く、明日中断することができる。 –

+1

また、効率的になりたいのであれば、Linqは通常正しい解決策ではありません –

+0

時間が分単位で配列の配列が必要ですか? – LiverpoolOwen

答えて

5

これはLinqの悪い候補だと思います。私は簡単な列挙のために行くだろう:

public static IEnumerable<KeyValuePair<DateTime, int>> Filter(IEnumerable<KeyValuePair<DateTime, int>> values) 
{ 
    KeyValuePair<DateTime, int>? previous = null; 

    foreach (var kvp in values.OrderBy(v => v.Key)) 
    { 
     if (previous == null || (kvp.Key - previous.Value.Key).TotalMinutes >= 1) 
     { 
      previous = kvp; 
      yield return kvp; 
     } 
    } 
} 

それからちょうどそれを列挙し、その結果であなたが必要とするものは何でも:

foreach (var value in Filter(dictionary)) 
{ 
    Console.WriteLine($"{value.Key} - {value.Value}"); 
} 

楽しいだけ、LINQのバージョン(のためにしてください、してください、それを使用しないでください):

public static IEnumerable<KeyValuePair<DateTime, int>> FilterLinq(IEnumerable<KeyValuePair<DateTime, int>> values) 
{ 
    KeyValuePair<DateTime, int>? previous = null; 

    return from kvp in values 
      orderby kvp.Key 
      where previous == null || (kvp.Key - previous.Value.Key).TotalMinutes >= 1 
      select (previous = kvp).Value; 
} 
+0

ありがとう、私はそれを試してみましょう。 – pitersmx

2

私はLINQが行くことをお勧めしますここでの選択肢。通常、維持するのは簡単ですが、パフォーマンス損失は無視できないほどです。

これを試してみてください:

var filtered = 
    pairs.Skip(1).Aggregate(pairs.Take(1).ToList(), (a, p) => 
    { 
     if (p.Key.Subtract(a.Last().Key).TotalMinutes >= 1.0) 
     { 
      a.Add(p); 
     } 
     return a; 
    }).ToList(); 

これが与える:あなたはまだそれらを並べ替える必要がありますreorder`する必要はありませんので、

filtered

+2

「集約」が私が思ったより強力であることを知りました。 –

関連する問題