2013-07-29 8 views
7

現在のオブジェクトと次のオブジェクトの計算を行うために、順序付けられたリストを歩くための洗練されたソリューションはありますか?次の操作を実行するためにLINQで賢く方法があるに違いありません:LINQを使用して現在のオブジェクトと次のオブジェクトの計算を行う

public static List<double> GetHoursBetweenDates(List<DateTime> aDates) 
{ 
    List<double> lst = new List<double>(); 
    var olst = aDates.OrderByDescending(d => d).ToList(); 
    for (int i = 0; i < olst.Count - 1; i++) 
    { 
     lst.Add(olst[i].Subtract(olst[i+1]).TotalHours); 
    } 
    return lst; 
} 
+1

「DateTime」オブジェクトを盲目的に区別するように注意してください。 '.Kind'は結果に影響します。 [この回答](http://stackoverflow.com/a/17950820/634824)と[この記事](http://codeofmatt.com/2013/04/25/the-case-against-datetime-now/)を参照してください。 )。 –

+0

ありがとう@Matt私はそれを念頭に置いておきます。 – Seatech

答えて

11

リスト内の各連続した要素を比較するのが最も簡単にはこのようなものです:

また
var sorted = aDates.OrderByDescending(d => d); 
var results = 
    sorted.Zip(sorted.Skip(1), (a, b) => a.Subtract(b).TotalHours); 

、あなたがこれを行うことができます:

var sorted = aDates.OrderByDescending(d => d).ToArray(); 
var results = 
    from i in Enumerable.Range(0, sorted.Length - 1) 
    select sorted[i].Subtract(sorted[i + 1]).TotalHours; 

しかし、この第二の方法はList<T>T[]または配列形式のインデクサーをサポートしている任意の型を動作します。

あなたが moreLINQライブラリから Incremental拡張メソッドを使用することができます
4

public static List<double> GetHoursBetweenDates(List<DateTime> aDates) 
{ 
    return aDates.OrderByDescending(d => d) 
       .Incremental((p,n) => p.Subtract(n).TotalHours) 
       .ToList(); 
} 

それはあなたが必要な正確に何を行います

/// <summary> 
/// Computes an incremental value between every adjacent element in a sequence: {N,N+1}, {N+1,N+2}, ... 
/// </summary> 
/// <remarks> 
/// The projection function is passed the previous and next element (in that order) and may use 
/// either or both in computing the result.< 
/// If the sequence has less than two items, the result is always an empty sequence. 
/// The number of items in the resulting sequence is always one less than in the source sequence. 
/// </remarks> 
7

する必要がありますLINQのZip列挙子を使用したソリューションの代替としてあなたのリストを2回繰り返します。ここでは、シーケンスを繰り返し、要素の「移動ペア」を返すカスタムLINQ演算子があります。

static IEnumerable<Tuple<T, T>> Pairwise<T>(this IEnumerable<T> xs) 
{ 
    using (IEnumerator<T> enumerator = xs.GetEnumerator()) 
    { 
     if (!enumerator.MoveNext()) yield break; 
     T current = enumerator.Current; 
     while (enumerator.MoveNext()) 
     { 
      T previous = current; 
      current = enumerator.Current; 
      yield return Tuple.Create(previous, current); 
     } 
    } 
} 

次のようにあなたは、あなたのDateTimeシーケンスに適用することができます:

dates.Pairwise().Select(_ => _.Item2.Subtract(_.Item1).TotalHours); 
9

その他のオプションは、集計関数を使用することで、現在の要素を集約として返します。

public static List<double> GetHoursBetweenDates(List<DateTime> aDates) 
{ 
    List<double> lst = new List<double>(); 
    aDates.OrderByDescending(d => d).Aggregate((prev, curr) => { lst.Add(prev.Subtract(curr).TotalHours); return curr; }); 
    return lst; 
} 
関連する問題