Is there an elegant solution to walk through an ordered list to do some calculations on the current and the next object? There must be a smarter way with LINQ to do the following:
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;
}
First(); var next = items . OrderBy(item => item.Id) . First(item => item.Id > currentId); var next = items .
While the LINQ methods always return a new collection, they don't create a new set of objects: Both the input collection (customers, in my example) and the output collection (validCustomers, in my previous example) are just sets of pointers to the same objects.
You can use LINQ to query any enumerable collections such as List<T>, Array, or Dictionary<TKey,TValue>. The collection may be user-defined or may be returned by a . NET API. In a basic sense, LINQ to Objects represents a new approach to collections.
The Any operator is used to check whether any element in the sequence or collection satisfy the given condition. If one or more element satisfies the given condition, then it will return true. If any element does not satisfy the given condition, then it will return false.
The easiest to compare each consecutive element in a list is something like this:
var sorted = aDates.OrderByDescending(d => d);
var results =
sorted.Zip(sorted.Skip(1), (a, b) => a.Subtract(b).TotalHours);
Alternatively, you can do this:
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;
But this second method will only work List<T>
, T[]
or any type which supports array-style indexers.
As an alternative to a solution using LINQ's Zip
enumerator, which requires you to iterate over your list twice, here's a custom LINQ operator that iterates over a sequence and returns a "moving pair" of elements:
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);
}
}
}
You could then apply it to your DateTime
sequence as follows:
dates.Pairwise().Select(_ => _.Item2.Subtract(_.Item1).TotalHours);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With