What other Enumerable extension methods would you like to see?

A few questions on Stack Overflow have suggested to me that there might be some bits missing from LINQ to Objects. There's the idea of a "zip" operator, which pairs up two sequences, for instance. Or the ability to apply the set operators with projections, e.g. DistinctBy, IntersectBy etc (mirroring OrderBy). They're easy to implement, but it would be nice to get a list of what people would like to see.

So, what's missing?

Published Thu, Oct 23 2008 21:50 by skeet
Filed under: ,

Comments

# re: What other Enumerable extension methods would you like to see?

It's not a part of LINQ to Objects, but I've always missed a method in Enumerable to just make an IEnumerable with one object. Sometimes you want to Concat a chain of items together and one or several of the steps just consist of a single item; today you have to construct an array or a list with an initializer and pass that, which distracts a bit and makes you figure out the most optimal choice (array).

I guess you could use Enumerable.Repeat(obj, 1), but that reads badly. And I guess the problem could be solved by just adding the overload Enumerable.Concat(params T[] items) which would have the compiler and JIT do a passable encapsulation for you.

Thursday, October 23, 2008 4:17 PM by Jesper

# re: What other Enumerable extension methods would you like to see?

Thursday, October 23, 2008 6:07 PM by John S.

# re: What other Enumerable extension methods would you like to see?

MinOrDefault([optional T item]) .. a wrapper for enumerable.DefaultIfEmpty().Min().

MaxOrDefault(...) .. same.

IndexOf(T item) .. the opposite of ElementAt().

Do(Action<T>) or ForEach(Action<T>) perhaps?

Thursday, October 23, 2008 9:51 PM by Jason

# re: What other Enumerable extension methods would you like to see?

Zip would, of course, be very useful, but would probably require a standard Tuple<> class in the framework; we've also already implemented our own DistinctBy extension method.

Other methods we've implemented in our standard utility library are:

Any (that returns bool, and has an out parameter that returns the item that matched the predicate)

IEnumerable<T> Append(IEnumerable<T> items, T item); Prepend

ForEach(IEnumerable<T>, Action<T>)

Max & Min (with custom comparers)

HashSet<T> ToSet(IEnumerable<T>)

We've also created extension methods on IList<T>, such as AsReadOnly, CopyTo, FindIndex, etc.

Thursday, October 23, 2008 11:37 PM by Bradley Grainger

# re: What other Enumerable extension methods would you like to see?

public static IEnumerable<T> Concat<T>(this T obj, IEnumerable<T> tail)

{

   yield return obj;

   foreach (var tailObj in tail)

       yield return tailObj;

}

// Matches "First", but alternatively called "Head" and "Tail".

public static IEnumerable<T> Rest<T>(this IEnumerable<T> enumerable)

{

   using (var enumerator = enumerable.GetEnumerator())

   {

       if (enumerator.MoveNext())

           while (enumerator.MoveNext())

               yield return enumerator.Current;

   }

}

Friday, October 24, 2008 12:05 AM by Brandon Bloom

# re: What other Enumerable extension methods would you like to see?

ForEach()

like in List<T>

Friday, October 24, 2008 1:07 AM by Krzysztof Koźmic

# re: What other Enumerable extension methods would you like to see?

I'm not sure all these extension methods need to be standard (don't want to pollute the namespace too much), but I'd greatly appreciate a means to filter IEnumerable which is order-aware: I want to process it like a stream of elements.

I frequently want to split a list in a specific spot after seeing a specific element (or sequence of elements).  Or, I don't want a mere where clause filter, I want to split the stream: basically an elementwise switch statement.  Doing this in LINQ now means repeating the same query several times using a  different where clause for each switch case (slow).  The alternative isn't attractive either, since a custom implementation will need to fight LINQ's pull semantics: if you split an Enumerable, and then iterate over one branch, you'll need to decide what to do with the other branch - cache it? discard and rerun?

Going into an even more speculative realm, a hypothetical LINQ for true element streams would be even fancier if they supported a regular expression kind of syntax backed by an NFA/DFA, for simple yet efficient expression of trivial context-dependent processing.

Friday, October 24, 2008 3:37 AM by Eamon Nerbonne

# re: What other Enumerable extension methods would you like to see?

@Eamon - have you looked at Push LINQ (MiscUtil)? It would seem to do most of what you want.

@Bradley - your Min/Max are already in MiscUtil (EnumerableExt)

@Brandon - isn't Rest the same as .Skip(1)?

@Jon - another one from SO: perhaps an AddRange<T>(this ICollection<T> x, IEnumerable<T> y)

Friday, October 24, 2008 8:10 AM by Marc Gravell

# re: What other Enumerable extension methods would you like to see?

@John S - Actually easier than that SO answer makes it look. Would be trivial to add to MiscUtil (which I suspect is what Jon intends...).

Friday, October 24, 2008 8:12 AM by Marc Gravell

# re: What other Enumerable extension methods would you like to see?

My favorite missing function is Iterate

       public class Pair<T> {

           public int Index;

           public T Value;

           public Pair(int i, T v) {

               Index = i;

               Value = v;

           }

       }

       static IEnumerable<Pair<T>> Iterate<T>(this IEnumerable<T> source) {

           int index = 0;

           foreach (var cur in source) {

               yield return new Pair<T>(index, cur);

               index++;

           }

       }

Friday, October 24, 2008 11:26 AM by JaredPar

# re: What other Enumerable extension methods would you like to see?

JaredPar: There's an overload of Select() that already does that.

Friday, October 24, 2008 12:40 PM by Jason

# re: What other Enumerable extension methods would you like to see?

I don't know the right name for these overloaded extensions, but I'd love to see something like:

IEnumerable<TPair> Slice<T,TResult>(this IEnumerable<T> seq, Func<T, T, TPair>) { }

IEnumerable<TTriple> Slice<T,TResult>(this IEnumerable<T> seq, Func<T, T, T, TTriple>) { }

etc...

Friday, October 24, 2008 7:13 PM by Jacob

# re: What other Enumerable extension methods would you like to see?

There are hot discussions about why .NET 3.5 doesn't have ForEach in class Enumerable.

Even though there are several reasons/excuses stated

1) List<T>.ForEach always shade extension method;

2) Enumerable methods should be chainable

I still would like to have ForEach in Enumerable.

Sunday, October 26, 2008 8:54 AM by Morgan Cheng

# re: What other Enumerable extension methods would you like to see?

@Morgan - re point 2, it still could be...

public static IEnumerable<T> ForEach<T>(this IEnumerable<T> source, Action<T> action) {

           foreach (T t in source) {

               action(t);

               yield return t;

           }

       }

Not sure if it is a great idea, but as a fluent API it seems fine (and still respects read-once streams without buffering).

Monday, October 27, 2008 10:31 AM by Marc Gravell

# re: What other Enumerable extension methods would you like to see?

(except of course you'd have to remember to terminate it! damned lazy execution... ;-p)

Monday, October 27, 2008 10:53 AM by Marc Gravell

# re: What other Enumerable extension methods would you like to see?

Given that ForEach() would do precisely the same as plain foreach, why would it be needed?

Tuesday, October 28, 2008 6:43 AM by Pavel Minaev

# re: What other Enumerable extension methods would you like to see?

@Marc:

Having implemented a chained foreach, I don't think it's a good idea.  It leads to some very un-obvious behavior that's difficult to debug.

In any event, of course, foreach is in the Parallel Extensions.  At least, for parallelizeable applications of foreach (and if they're not, perhaps you should consider refactoring them).

@Jacob:

I seem to recall seeing an ArraySlice internal to WPF.  I could be wrong.  But I think I'd rather see that than a direct enumeration.  Further, since slices preclude indexes, I'd strongly suggest favoring IList rather than IEnumerable in this case.

class Slice<T>: IList<T>

{

   public Slice(

       IEnumerable<T> source,

       int startIndex,

       int maxItems)

   { ... }

   List<T> cache;

   // implementation of IList<T> doesn't bother enumerating until it needs to, then only enumerates as far as the highest index it needs.  

   // In the case of an IList as input, it can do direct indexing rather than enumeration.

}

Friday, October 31, 2008 4:02 AM by Keith J. Farmer

# re: What other Enumerable extension methods would you like to see?

What I would like to see?

Converters between streams, event sequences, and enumerables.  I've written them to handle serial ports protocols, and they're not fun.

class StreamSource<out TOut>

{

   Stream Input;

   Action<byte, Action> Aggregator;

   event EventHandler<TOut> Output;

}

class EventSource<in TIn, out TOut>: IEnumerable<TOut>

{

   Func<TIn, TOut> projector;

   // listens to one or more EventHandler<TIn>,

   // and buffers a projection

   // of the event args

}

Friday, October 31, 2008 4:15 AM by Keith J. Farmer

# re: What other Enumerable extension methods would you like to see?

Some "experimental" extension methods:

(links to automatic translation from Google, sorry, original is in czech language, but code is self-explanatory, I hope).

Casting generic collections (workarounds not needed in C# 4.0)

http://tinyurl.com/6lag3b

Hack for anonymous type

http://tinyurl.com/65yt4m

Emulation of Bind1St, Bind2nd in C++, "adapters" Not, And, ToPredicate etc.

http://tinyurl.com/6pl663

Friday, November 07, 2008 5:09 AM by Rene

# re: What other Enumerable extension methods would you like to see?

I've been trying to code some F# in C#, and ended up rolling the following 'missing' links:

MapI, FoldI.

A while ago I was also surprised not to find ForEach in IEnumerable, but having rolled my own, I was even more surprised when nothing happened! Having thought further, I decided on two extension methods:

public static void Iter<T>(this IEnumerable<T> input, Action<T> action)

{

  input.ToList().ForEach(action);

}

(I consider this to be justified, on the basis of Seq.iter)

And this 'pass-through' extension (which I'm slightly less easy with, I first thought of calling it 'Log', but SideEffects is a better warning):

public static IEnumerable<T> SideEffects<T>(this IEnumerable<T> items, Action<T> pPerfomAction)

{

   foreach (T item in items)

   {

       pPerfomAction(item);

       yield return item;

   }

}

Then there are these two: stackoverflow.com/.../pipe-forwards-in-c

Thursday, December 04, 2008 1:12 AM by Ben

# re: What other ... Iterator.remove()

I sorely miss the ability to remove certain elements from a collection -

I would like to see something like Java's Iterator.remove()

Monday, December 29, 2008 4:06 PM by Jiri Moudry

# Designing LINQ operators

I've started a small project (I'll post a link when I've actually got something worthwhile

Friday, January 23, 2009 5:40 PM by Jon Skeet: Coding Blog

# re: What other Enumerable extension methods would you like to see?

PositionalJoin (see stackoverflow.com/.../join-of-time-series) is interesting. What I'd really like to see though is for specialized collections such as System.Windows.Forms.ControlCollection to be retrofitted with the correct IEnumerable<T> interface so Linq to Objects queries can be used against them without first having to do a Cast<T>().

Saturday, January 24, 2009 9:46 PM by Luke Sandell

# ForEach

In my recent post about coding styles one particular thing provoked the majority of feedback and discussions:

Sunday, February 01, 2009 1:41 AM by Kirill Osenkov

# re: What other Enumerable extension methods would you like to see?

From my own extensions project on Codeplex - NExtension:

Clump - Reverses SelectMany by clumping a flat list into list of lists of a fixed size.

AtLeast - Similar to Any, but can check for "at least x" number of items instead of just 1.

AtMost - Same as AtLeast, but for All. Checks for "at most x" number of items.

These and Zip are probably the most useful. Feel free to use.

Friday, February 06, 2009 8:46 AM by Cameron MacFarland