Home > Programming > LINQ: working with pairs of items in a list

LINQ: working with pairs of items in a list

I’m learning about LINQ (I’ve been in a .NET vacuum due to work, so I need to catch up).

One of the things I do often with my current language tools is work on operations on sequential pairs in a list. LINQ makes that incredibly compact with Zip and Skip. I just don’t like the name “Zip” for this (too many things called Zip), so I made my own extension:

public static Extensions
{
    public static TResult[] WithNext<T, TResult>
        (this T[] source, Func<T, T, TResult> operation)
    {
        return source.Zip(source.Skip(1), operation).ToArray();
    }
}

Example of usage:

DateTime[] dts = // get a list of DateTimes.
TimeSpan diffs = dts.WithNext((x,y) => y - x);

That’s it, give it a list of DateTimes, get the difference between each (as TimeSpans). Final array is 1 element shorter. If the original list is 0 or 1 elements long, Zip is smart enough to return an empty set.

The reason why I extend it on array (T[]) instead of IEnumerable<T> is subtle. It was brought to me by a colleague. What generic collections implement IEnumerable<T>?

  • Dictionary<TKey,TValue>
  • HashSet<T>
  • LinkedList<T>
  • List<T>
  • Queue<T>
  • SortedDictionary<TKey,TValue>
  • SortedList<TKey,TValue>
  • SortedSet<TKey,TValue>
  • Stack<T>

IEnumerable<T> allows the use of foreach and LINQ functions (and probably some other stuff I’m not remembering right now). It’s great that way. But what foreach and LINQ do is they call up the enumerator and go through each item in the list, but there’s no notion of order in most of of these collections. That DateTime list turned into differences only makes sense if the times are sorted. And some collections have no guarantee on the order given from their enumerator. So instead, tying WithNext to T[] forces the use of an array (which arguably should be sorted), and prevents the use of a generic collection where the operation would not make sense.


UPDATE (2011-11-02)

After some thinking (and headbanging with above mentioned colleague), the extension function could also be made to return an IEnumerable list. That list should respect the original order used (for lists where order makes sense):

public static Extensions
{
    public static IEnumerable<TResult> WithNext<T, TResult>
        (this T[] source, Func<T, T, TResult> operation)
    {
        return source.Zip(source.Skip(1), operation);
    }
}
Advertisements
Categories: Programming Tags: ,
  1. 2014-05-01 at 3:45 pm

    Hello just wanted to give you a quick heads up.
    The text in your article seem to be running off
    the screen in Firefox. I’m not sure if this is a format
    issue or something to do with browser compatibility but I thought
    I’d post to let you know. The layout look great though!

    Hope you get the issue solved soon. Thanks

    • MPelletier
      2014-05-05 at 7:47 am

      Thanks for the warning. I only use stock WordPress themes and features, so it must be an issue on their side.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: