By Nappy


2010-09-05 09:49:20 8 Comments

With extension methods, we can write handy LINQ operators which solve generic problems.

I want to hear which methods or overloads you are missing in the System.Linq namespace and how you implemented them.

Clean and elegant implementations, maybe using existing methods, are preferred.

30 comments

@Mike 2018-07-02 20:57:13

Partition

Will split an IEnumerable into two ILists based on a condition

public static void Partition<T>(this IEnumerable<T> source, Func<T, bool> predicate, ref IList<T> matches, ref IList<T> nonMatches)
{
    if (source == null)
        throw new ArgumentNullException(nameof(source));
    if (predicate == null)
        throw new ArgumentNullException(nameof(source));

    var _matches = new List<T>();
    var _nonMatches = new List<T>();
    foreach (var itm in source)
    {
        if (predicate(itm))
            _matches.Add(itm);
        else
            _nonMatches.Add(itm);
    }

    if (matches == null)
        matches = new List<T>();
    else
        matches.Clear();
    if (nonMatches == null)
        nonMatches = new List<T>();
    else
        nonMatches.Clear();

    foreach (var m in _matches)
        matches.Add(m);
    nonMatches.Clear();
    foreach (var m in _nonMatches)
        nonMatches.Add(m);
    nonMatches = _nonMatches;
}

@Handcraftsman 2010-09-05 16:44:40

Shuffle

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> items)
{
    var random = new Random();
    return items.OrderBy(x => random.Next());
}

EDIT: It seems there are several issues with the above implementation. Here is an improved version based @LukeH's code and comments from @ck and @Strilanc.

private static Random _rand = new Random();
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
{
    var items = source == null ? new T[] { } : source.ToArray();
    var count = items.Length;
    while(count > 0)
    {
        int toReturn = _rand.Next(0, count);
        yield return items[toReturn];
        items[toReturn] = items[count - 1];
        count--;
    }
}

@Nappy 2010-09-05 19:52:50

I would propose to rename this to either Randomize or Shuffle.

@cjk 2010-09-06 07:40:13

This might be better with a static Random object.

@Scott Mitchell 2010-09-10 20:08:46

Rather than using Random, you could just order using new GUID values - items.OrderBy(x => Guid.NewGuid()).

@Handcraftsman 2010-09-11 14:11:25

@Scott guids are unique but are not guaranteed to be random. See: stackoverflow.com/questions/467271/…

@LukeH 2010-09-13 00:14:19

If you're going to include a Shuffle method in your library then you may as well make it as efficient an implementation as possible. Using OrderBy is O(n log n) whereas a Fisher-Yates-Durstenfeld shuffle will be O(n). Here's an example: stackoverflow.com/questions/1651619/…

@Scott Mitchell 2010-09-13 17:10:25

@Handcraftsman: True, GUIDs aren't guaranteed to be random, but IIRC they are "random enough" in the .NET implementation. I did some empirical tests that, obviously, don't PROVE anything, but they show the randomness of Guid.NewGuid(). See 4guysfromrolla.com/articles/070208-1.aspx. (Also, to be pedantic, the Random class isn't truly random, either. <g>)

@Craig Gidney 2010-09-25 05:37:32

Your implementation is wrong. Worse than that, it is SUBTLY wrong. First, it has a hidden global dependency: the source of randomness (even worse, the source you chose will give the same shuffles if quickly called multiple times!). Second, the algorithm used is bad. Not only is it asymptotically slower than Fisher-Yates, it isn't uniform (elements assigned the same key stay in the same relative order).

@Nappy 2011-07-12 15:00:25

I would probably add the random source as a parameter. This hast two advantages: You do not create multiple Random sources at startup, or at least it is the responsiveness of the developer to initialize them correctly, and second, if applied consistently its a good indicator, that the method returns different/random results each time.

@KeithS 2015-08-11 17:10:45

@Nappy Unfortunately most sources of randomness in .NET don't have the same external interface; contrast Math.Random with implementations of System.Security.Cryptography.RandomNumberGenerator. You can write adapters and/or accept a simple Func<int> but someone has to do the work of simplifying the way that the method gets its PRNs.

@Omer Raviv 2010-12-26 08:34:33

GetBreadthFirstEnumerable

This is my favorite - does Breadth First Search over any collection quite easily. At each iteration, the method yield the current node, its parent, the level it is in the graph, and its index in breadth-first-order. This is great help in some scenarios, but if you don't need it, the method can be greatly simplified, if you want - you can yield only the node itself.

public class IteratedNode<T>
{
    public T Node;
    public T ParentNode;
    public int Level;
    public int Index;
}

/// <summary>
/// Iterates over a tree/graph via In Order Breadth First search.
/// </summary>
/// <param name="root">The root item.</param>
/// <param name="childSelector">A func that receives a node in the tree and returns its children.</param>
public static IEnumerable<IteratedNode<T>> GetBreadthFirstEnumerable<T>(this T root, Func<T, IEnumerable<T>> childSelector)
{
    var rootNode = new IteratedNode<T> { Node = root, ParentNode = default(T), Level = 1, Index = 1};
    var nodesToProcess = new Queue<IteratedNode<T>>( new[] {rootNode});

    int itemsIterated = 0;
    while (nodesToProcess.Count > 0)
    {
        IteratedNode<T> currentItem = nodesToProcess.Dequeue();

        yield return currentItem; itemsIterated++;

        // Iterate over the children of this node, and add it to queue, to process later.
        foreach (T child in childSelector(currentItem.Node))
        {
            nodesToProcess.Enqueue( 
                new IteratedNode<T> {
                    Node = child,
                    ParentNode = currentItem.Node,
                    Level = currentItem.Level + 1,
                    Index = itemsIterated
                });                      
        }
    }
}

@Salar 2012-08-19 04:51:08

/// <summary>
/// Performs the specified action on each element of the IEnumerable.
/// </summary>
public static void ForEachAction<T>(this IEnumerable<T> enumerable, Action<T> action)
{
    if (action == null || enumerable == null)
    {
        throw new ArgumentNullException();
    }

    foreach (var item in enumerable)
    {
        action.Invoke(item);
    }
}

@KeithS 2012-03-30 17:16:00

ObjectWithMin/ObjectWithMax

Similar to Timwi's MinElement, but there's a more concise algorithm using the Aggregate extension method to spin through the source Enumerable:

public static T ObjectWithMax<T, TResult>(this IEnumerable<T> elements, Func<T, TResult> projection)
    where TResult : IComparable<TResult>
{
    if (elements == null) throw new ArgumentNullException("elements", "Sequence is null.");
    if (!elements.Any()) throw new ArgumentException("Sequence contains no elements.");

    //Set up the "seed" (current known maximum) to the first element
    var seed = elements.Select(t => new {Object = t, Projection = projection(t)}).First();

    //run through all other elements of the source, comparing the projection of each
    //to the current "seed" and replacing the seed as necessary. Last element wins ties.
    return elements.Skip(1).Aggregate(seed,
                              (s, x) =>
                              projection(x).CompareTo(s.Projection) >= 0
                                  ? new {Object = x, Projection = projection(x)}
                                  : s
        ).Object;
}

public static T ObjectWithMin<T, TResult>(this IEnumerable<T> elements, Func<T, TResult> projection)
    where TResult : IComparable<TResult>
{
    if (elements == null) throw new ArgumentNullException("elements", "Sequence is null.");
    if (!elements.Any()) throw new ArgumentException("Sequence contains no elements.");

    var seed = elements.Select(t => new {Object = t, Projection = projection(t)}).First();

    //ties won by the FIRST element in the Enumerable
    return elements.Aggregate(seed,
                              (s, x) =>
                              projection(x).CompareTo(s.Projection) < 0
                                  ? new {Object = x, Projection = projection(x)}
                                  : s
        ).Object;
}

I have found these methods invaluable compared to OrderBy().First() or Where(x=>x.SomeField == source.Min(someField)).First(). It's linear, goes through the Enumerable only once, and is stable to the current order of the list.

@Stéphane Gourichon 2015-08-11 14:10:46

Why the asymmetry between ties?

@KeithS 2015-08-11 17:02:43

@StéphaneGourichon - Good question. I did it that way to make the methods behave similarly to stable sorts. In such a sort, relative order is the tiebreaker; when two elements compare as "equal", whichever was first is considered to be "less than" the one that came second. This stability is generally considered an advantage of a sorting algorithm. My methods above honor the relative order of elements in a similar way; the first occurrence of the minimum value is treated as the least, and the last occurrence of the maximum value is treated as greatest.

@KeithS 2012-03-30 17:03:37

Except with params list

This is a really simple wrapper that can make certain queries much easier:

public static IEnumerable<T> Except<T>(this IEnumerable<T> elements, params T[] exceptions)
{
    return elements.Except(exceptions);
}

Usage:

//returns a list of "work week" DayOfWeek values.
Enum.GetValues(typeof(DayOfWeek)).Except(DayOfWeek.Saturday, DayOfWeek.Sunday);

This prevents having to create your own collection to pass into Except, or using Where with a large Boolean "doesn't equal A and doesn't equal B and..." construct, making code a bit cleaner.

Except with Predicate (Inverse Where)

I have also seen Except given a predicate, basically making it an inverse of Where, and the easiest implementation is exactly that:

public static IEnumerable<T> Except<T>(this IEnumerable<T> elements, Predicate<T> predicate)
{
   return elements.Where(x=>!predicate(x));
}

Usage:

//best use is as a "natural language" statement already containing Where()
ListOfRecords.Where(r=>r.SomeValue = 123).Except(r=>r.Id = 2536);

If C# has both do-while and do-until constructs, this has its place.

@aboveyou00 2012-01-16 14:29:17

Mine is RemoveConcurrent<T>():

public static IEnumerable<T> RemoveConcurrent<T>(this IEnumerable<T> ts) where T : IEquatable<T>
{
    bool first = true;
    T lval = default(T);
    foreach (T t in ts)
    {
        if (first || !t.Equals(lval))
        {
            first = false;
            yield return t;
        }
        lval = t;
    }
}

There may be a way to do this with the standard LINQ queries, but if so, I don't know how.

@Nappy 2012-01-16 16:38:12

In System.Interactive (Ix) / System.Reactive (Rx) this one is called "DistinctUntilChanged" which probably is a more intuitive name, but yeah its a very useful operator.

@noopman 2010-09-06 11:22:32

One, Two, MoreThanOne, AtLeast, AnyAtAll

public static bool One<T>(this IEnumerable<T> enumerable)
{
    using (var enumerator = enumerable.GetEnumerator())
        return enumerator.MoveNext() && !enumerator.MoveNext();
}

public static bool Two<T>(this IEnumerable<T> enumerable)
{
    using (var enumerator = enumerable.GetEnumerator())
        return enumerator.MoveNext() && enumerator.MoveNext() && !enumerator.MoveNext();
}

public static bool MoreThanOne<T>(this IEnumerable<T> enumerable)
{
    return enumerable.Skip(1).Any();
}

public static bool AtLeast<T>(this IEnumerable<T> enumerable, int count)
{
    using (var enumerator = enumerable.GetEnumerator())
        for (var i = 0; i < count; i++)
            if (!enumerator.MoveNext())
                return false;
    return true;
}

public static bool AnyAtAll<T>(this IEnumerable<T> enumerable)
{
    return enumerable != null && enumerable.Any();
}

@Bear Monkey 2010-09-06 12:20:58

Do not forget to wrap enumerator in a using statement.

@Timwi 2010-09-07 02:52:01

I’ve taken the liberty to remove ToEnumerable because it does not appear to be related to the others, and it has already been posted in another answer anyway.

@noopman 2010-09-07 05:11:41

Well Timwi if you'd examined the implementations of ToEnumerable more closely you'd find that they were not the same. My version takes an arbitrary set and turns into an enumerable. That's not the same function someone else posted. But sure... go ahead and take liberties.

@Bear Monkey 2010-09-23 08:27:38

+1 I like these methods. I have similar methods defined in my own utils library. IMO AnyAtAll would be easier to understand if you inverted it and called it IsNullOrEmpty.

@noopman 2010-09-28 07:13:34

I kind of agree but still. .AnyAtAll() is in reference to .Any() which throws on null.

@KeithS 2015-08-11 17:16:03

I have a very similar "One" function in my own library of extension methods. It could also be useful to overload these to accept projections, the way Any, First etc do.

@Timwi 2010-09-05 10:37:44

JoinString

Basically the same as string.Join, but:

  • with the ability to use it on any collection, not just a collection of strings (calls ToString on every element)

  • with the ability to add a prefix and suffix to every string.

  • as an extension method. I find string.Join annoying because it is static, meaning that in a chain of operations it is lexically not in the correct order.


/// <summary>
/// Turns all elements in the enumerable to strings and joins them using the
/// specified string as the separator and the specified prefix and suffix for
/// each string.
/// <example>
///   <code>
///     var a = (new[] { "Paris", "London", "Tokyo" }).JoinString(", ", "[", "]");
///     // a contains "[Paris], [London], [Tokyo]"
///   </code>
/// </example>
/// </summary>
public static string JoinString<T>(this IEnumerable<T> values,
    string separator = null, string prefix = null, string suffix = null)
{
    if (values == null)
        throw new ArgumentNullException("values");

    using (var enumerator = values.GetEnumerator())
    {
        if (!enumerator.MoveNext())
            return "";
        StringBuilder sb = new StringBuilder();
        sb.Append(prefix).Append(enumerator.Current.ToString()).Append(suffix);
        while (enumerator.MoveNext())
            sb.Append(separator).Append(prefix)
              .Append(enumerator.Current.ToString()).Append(suffix);
        return sb.ToString();
    }
}

@Christian Hayter 2010-09-05 11:11:50

Very useful, although personally I would take out all the formatting code and just have the ability to join IEnumerable<string> with a separator. You can always project the data to IEnumerable<string> before calling this method.

@Ani 2010-09-05 14:46:54

@Timwi: A few minor points: You don't need the null checks before appending to the StringBuilder. You need to dispose the enumerator. You can get rid of the Append calls above the while loop and replace the loop with do-while. Finally, unless you want to avoid paying the cost of creating a StringBuilder, you don't need to treat the first element as a special-case: new StringBuilder().ToString() will return string.Empty.

@Timwi 2010-09-05 16:19:33

@Ani: Thanks, I’ve made most of those fixes. I do prefer for library code to be as fast as possible in tight loops, so I’ll keep the special-casing and the appends before the while.

@Ian Mercer 2010-09-05 23:07:42

String.Join in .NET 4 takes an IEnumerable<T>.

@Timwi 2010-09-05 23:32:07

@cjk 2010-09-06 07:39:34

I like this one.

@Kirk Broadhurst 2010-09-12 13:52:52

Does this do anything that we don't already have with the Aggregate operator? It's an unusual one to use but can definitely be used for joining lists of objects.

@Timwi 2010-09-12 19:05:05

@Kirk Broadhurst: Well, for one, Aggregate would be slower if you concatenate strings at each stage instead of using a StringBuilder. But for two, even if I wanted to use Aggregate for this, I would still wrap it into a JoinString method with this signature because it makes the code using it much clearer. And once I have that, I might as well write the method to be faster by using a StringBuilder.

@Gabe 2010-09-26 05:43:49

OneOrDefault

Like SingleOrDefault, only it returns null instead of throwing an exception when there are multiple elements in the list.

public static T OneOrDefault<T>(this IEnumerable<T> list)
{
    using (var e = list.GetEnumerator())
    {
        if (!e.MoveNext())
            return default(T);
        T val = e.Current;
        if (e.MoveNext())
            return default(T);
        return val;
    }
}

@M4N 2010-09-26 09:51:35

Isn't this the same as FirstOrDefault(): msdn.microsoft.com/en-us/library/bb358452.aspx

@Gabe 2010-09-26 15:01:58

M4N: No, FirstOrDefault doesn't call MoveNext a second time.

@Stéphane Gourichon 2015-08-11 14:03:19

@Gabe what's the point of calling or not MoveNext() a second time? Can you tell a practical use case for OneOrDefault? Thanks.

@Gabe 2015-09-11 05:04:02

@StéphaneGourichon: If you don't have the second MoveNext, you get FirstOrDefault. If you have the second MoveNext and throw an exception if it returns true, you get SingleOrDefault. If you have the second and return default, you get OneOrDefault.

@John Egbert 2010-09-10 16:18:37

public static void AddRangeWhere<T>(this IEnumerable<T> list, IEnumerable<T> sourceList, Func<T, bool> predicate)
  {
   if (list != null)
   {
    List<T> newRange = new List<T>();

    foreach (var item in sourceList)
    {
     if (predicate(item))
      newRange.Add(item);
    }

    list.Concat(newRange);
   }
  }

@Nevermind 2010-09-09 11:49:47

EnumerableEx.OfThese:

public static class EnumerableEx
{
    public static IEnumerable<T> OfThese<T>(params T[] objects)
    {
        return objects;
    }
}

To easily construct sequences of known values:

var nums=EnumerableEx.OfThese(1,2,3);
var nums2 = nums.Concat(EnumerableEx.OfThese(4));

@Bear Monkey 2010-09-10 22:36:52

Its a good idea but this extension method is longer and not as clear as simple writing -> var nums = new int[] { 1, 2, 3};

@Nevermind 2010-09-13 08:27:16

I believe it is actually clearer, when you need "just a sequence", and don't care whether it is an array, list or whatever.

@Gabe 2010-09-26 05:41:29

Best use of the identity function I've seen yet!

@dkackman 2010-09-05 21:56:54

WhereLike

Combines Where with SQL LIKE pattern matching.

public static IEnumerable<TSource> WhereLike<TSource>(this IEnumerable<TSource> source, Func<TSource, string> selector, string match)
    {
        /* Turn "off" all regular expression related syntax in
            * the pattern string. */
        string pattern = Regex.Escape(match);

        /* Replace the SQL LIKE wildcard metacharacters with the
        * equivalent regular expression metacharacters. */
        pattern = pattern.Replace("%", ".*?").Replace("_", ".");

        /* The previous call to Regex.Escape actually turned off
        * too many metacharacters, i.e. those which are recognized by
        * both the regular expression engine and the SQL LIKE
        * statement ([...] and [^...]). Those metacharacters have
        * to be manually unescaped here. */
        pattern = pattern.Replace(@"\[", "[").Replace(@"\]", "]").Replace(@"\^", "^");
        Regex reg = new Regex(pattern, RegexOptions.IgnoreCase);

        return source.Where(t => reg.IsMatch(selector(t)));
    }

@Nappy 2010-09-06 14:05:58

Window

Enumerates arrays ("windows") with the length of size containing the most current values.
{ 0, 1, 2, 3 } becomes to { [0, 1], [1, 2], [2, 3] }.

I am using this for example to draw a line graph by connecting two points.

public static IEnumerable<TSource[]> Window<TSource>(
    this IEnumerable<TSource> source)
{
    return source.Window(2);
}

public static IEnumerable<TSource[]> Window<TSource>(
    this IEnumerable<TSource> source, int size)
{
    if (size <= 0)
        throw new ArgumentOutOfRangeException("size");

    return source.Skip(size).WindowHelper(size, source.Take(size));
}

private static IEnumerable<TSource[]> WindowHelper<TSource>(
    this IEnumerable<TSource> source, int size, IEnumerable<TSource> init)
{
    Queue<TSource> q = new Queue<TSource>(init);

    yield return q.ToArray();

    foreach (var value in source)
    {
        q.Dequeue();
        q.Enqueue(value);
        yield return q.ToArray();
    }
}

@noopman 2010-09-06 11:18:44

public static IEnumerable<T> Append<T>(this IEnumerable<T> enumerable, T item)
{
 return enumerable.Concat(new[] { item });
}

public static IEnumerable<T> AppendIf<T>(this IEnumerable<T> enumerable, T item, Func<bool> predicate)
{
 return predicate() ? enumerable.Append(item) : enumerable;
}

@Johann Blais 2010-09-06 07:37:42

In and NotIn

C# equivalents of two other well-known SQL constructs

/// <summary>
/// Determines if the source value is contained in the list of possible values.
/// </summary>
/// <typeparam name="T">The type of the objects</typeparam>
/// <param name="value">The source value</param>
/// <param name="values">The list of possible values</param>
/// <returns>
///     <c>true</c> if the source value matches at least one of the possible values; otherwise, <c>false</c>.
/// </returns>
public static bool In<T>(this T value, params T[] values)
{
    if (values == null)
        return false;

    if (values.Contains<T>(value))
        return true;

    return false;
}

/// <summary>
/// Determines if the source value is contained in the list of possible values.
/// </summary>
/// <typeparam name="T">The type of the objects</typeparam>
/// <param name="value">The source value</param>
/// <param name="values">The list of possible values</param>
/// <returns>
///     <c>true</c> if the source value matches at least one of the possible values; otherwise, <c>false</c>.
/// </returns>
public static bool In<T>(this T value, IEnumerable<T> values)
{
    if (values == null)
        return false;

    if (values.Contains<T>(value))
        return true;

    return false;
}

/// <summary>
/// Determines if the source value is not contained in the list of possible values.
/// </summary>
/// <typeparam name="T">The type of the objects</typeparam>
/// <param name="value">The source value</param>
/// <param name="values">The list of possible values</param>
/// <returns>
///     <c>false</c> if the source value matches at least one of the possible values; otherwise, <c>true</c>.
/// </returns>
public static bool NotIn<T>(this T value, params T[] values)
{
    return In(value, values) == false;
}

/// <summary>
/// Determines if the source value is not contained in the list of possible values.
/// </summary>
/// <typeparam name="T">The type of the objects</typeparam>
/// <param name="value">The source value</param>
/// <param name="values">The list of possible values</param>
/// <returns>
///     <c>false</c> if the source value matches at least one of the possible values; otherwise, <c>true</c>.
/// </returns>
public static bool NotIn<T>(this T value, IEnumerable<T> values)
{
    return In(value, values) == false;
}

@Timwi 2010-09-07 02:40:31

Instead of if (values == null) return false; I think it should throw an exception. Silently swallowing error conditions is never good.

@Johann Blais 2010-09-07 06:50:38

It depends on how you look at it. The fact is an element is never contained in an empty list of values.

@KeithS 2012-03-30 16:50:58

One thing, helps with DRY but increases the call stack; the params array, being an array, is IEnumerable, so your params overload can simply call the IEnumerable overload.

@nawfal 2014-01-27 09:57:40

Just return values.Contains(value); is enough.

@Johann Blais 2010-09-06 07:22:44

Between

C# equivalent of the well-known SQL "between" construct

/// <summary>
/// Determines if the current value is included in the range of specified values. Bounds are included.
/// </summary>
/// <typeparam name="T">The type of the values</typeparam>
/// <param name="val">The value.</param>
/// <param name="firstValue">The lower bound.</param>
/// <param name="secondValue">The upper bound.</param>
/// <returns>
/// Return <c>true</c> if the <paramref name="val">value</paramref> is between the <paramref name="firstValue"/> and the <paramref name="secondValue"/>; otherwise, <c>false</c>
/// </returns>
public static bool Between<T>(this T val, T firstValue, T secondValue) where T : IComparable<T>
{
  if (val == null)
    throw new ArgumentNullException();

  if (firstValue == null ||
      secondValue == null)
    return false;

  return firstValue.CompareTo(val) <= 0 && secondValue.CompareTo(val) >= 0;
}

@Timwi 2010-09-07 02:53:32

Not relevant to the question, which is about IEnumerable<T>.

@Johann Blais 2010-09-07 06:48:28

It is not strictly on the subject, but since LINQ to Object is all about narrowing the gap between SQL syntax and C# code, I think this Between operator fits pretty well in the big picture.

@mattmc3 2010-09-05 22:43:52

Coalesce

public static T Coalesce<T>(this IEnumerable<T> items) {
   return items.Where(x => x != null && !x.Equals(default(T))).FirstOrDefault();
   // return items.OfType<T>().FirstOrDefault(); // Gabe's take
}

@Gabe 2010-09-05 23:20:37

Since you're actually using it, allow me to simplify it for you.

@mattmc3 2010-09-06 00:00:12

No thanks. As your version only works with object types (not DateTime, etc.) and your usage of OfType<T> isn't typical since most people know it as a casting method and not a non-null filter, and since it doesn't add anything in terms of readability or performance, I'll stick with my original.

@Bear Monkey 2010-09-06 00:36:58

But OfType<T> does work with DateTime, no?. Also, I do think of OfType<T> as a non-null filtering method, how else would it work? Maybe its just me and Gabe...

@mattmc3 2010-09-06 00:57:22

OfType works with value types, sure. Though Gabe's usage changed the Coalesce method so that it doesn't work the way I want it to for value types. As far as OfType goes, I think of its usage more for heterogeneous or polymorphic collections where you want to filter by type (msdn.microsoft.com/en-us/library/bb360913.aspx). The MSDN article doesn't even mention filtering out nulls.

@mattmc3 2010-09-06 01:48:50

Made classic mistake when converting from VB to C#... Nothing is not equivalent to null... had to revise C# implementation.

@mattmc3 2010-09-07 15:34:43

@Timwi - Not exactly. I think you missed what this does. Make a DateTime array of [DateTime.MinDate, DateTime.Now] and pass it in. You'll get DateTime.Now which is what you want. Your way, you'd get DateTime.MinDate (equivalent to Nothing in VB).

@mattmc3 2010-09-08 12:42:48

@Timwi - great... it works for DateTime and other value types without the x != null, but you get a runtime error for objects if you cut out the x != null part. Geez people, how hard is it to open Visual Studio and test the code before commenting.

@Bear Monkey 2010-09-06 00:11:59

ToList and ToDictionary with Initial Capacity

ToList and ToDictionary overloads that expose the underlying collection classes' initial capacity. Occasionally useful when source length is known or bounded.

public static List<TSource> ToList<TSource>(
    this IEnumerable<TSource> source, 
    int capacity)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }
    var list = new List<TSource>(capacity);
    list.AddRange(source);
    return list;
}     

public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
    this IEnumerable<TSource> source, 
    Func<TSource, TKey> keySelector, 
    int capacity,
    IEqualityComparer<TKey> comparer = null)
{
    return source.ToDictionary<TSource, TKey, TSource>(
                  keySelector, x => x, capacity, comparer);
}

public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
    this IEnumerable<TSource> source, 
    Func<TSource, TKey> keySelector, 
    Func<TSource, TElement> elementSelector,
    int capacity,
    IEqualityComparer<TKey> comparer = null)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }
    if (keySelector == null)
    {
        throw new ArgumentNullException("keySelector");
    }
    if (elementSelector == null)
    {
        throw new ArgumentNullException("elementSelector");
    }
    var dictionary = new Dictionary<TKey, TElement>(capacity, comparer);
    foreach (TSource local in source)
    {
        dictionary.Add(keySelector(local), elementSelector(local));
    }
    return dictionary;
}

@Timwi 2010-09-05 10:22:29

MinElement

Min only returns the minimum value returned by the specified expression, but not the original element that gave this minimum element.

/// <summary>Returns the first element from the input sequence for which the
/// value selector returns the smallest value.</summary>
public static T MinElement<T, TValue>(this IEnumerable<T> source,
        Func<T, TValue> valueSelector) where TValue : IComparable<TValue>
{
    if (source == null)
        throw new ArgumentNullException("source");
    if (valueSelector == null)
        throw new ArgumentNullException("valueSelector");
    using (var enumerator = source.GetEnumerator())
    {
        if (!enumerator.MoveNext())
            throw new InvalidOperationException("source contains no elements.");
        T minElem = enumerator.Current;
        TValue minValue = valueSelector(minElem);
        while (enumerator.MoveNext())
        {
            TValue value = valueSelector(enumerator.Current);
            if (value.CompareTo(minValue) < 0)
            {
                minValue = value;
                minElem = enumerator.Current;
            }
        }
        return minElem;
    }
}

@Gabe 2010-09-05 22:22:48

It would be much preferable to either make valueSelector return an IComparable or change valueSelector to something like Func<T, T, bool> lessThan so that things like strings or decimals could be compared.

@Timwi 2010-09-05 23:19:24

@Gabe: Good idea!

@Dan Tao 2010-09-05 23:01:27

Loop

Here's a kinda cool one I just thought of. (If I just thought of it, maybe it's not that useful? But I thought of it because I have a use for it.) Loop through a sequence repeatedly to generate an infinite sequence. This accomplishes something kind of like what Enumerable.Range and Enumerable.Repeat give you, except it can be used for an arbitrary (unlike Range) sequence (unlike Repeat):

public static IEnumerable<T> Loop<T>(this IEnumerable<T> source)
{
    while (true)
    {
        foreach (T item in source)
        {
            yield return item;
        }
    }
}

Usage:

var numbers = new[] { 1, 2, 3 };
var looped = numbers.Loop();

foreach (int x in looped.Take(10))
{
    Console.WriteLine(x);
}

Output:

1
2
3
1
2
3
1
2
3
1

Note: I suppose you could also accomplish this with something like:

var looped = Enumerable.Repeat(numbers, int.MaxValue).SelectMany(seq => seq);

...but I think Loop is clearer.

@Gabe 2010-09-05 23:18:48

This implementation has the interesting property that it creates a new enumerator each time through, so it could give unexpected results.

@Dan Tao 2010-09-05 23:43:55

@Gabe: There's really no way to do it without creating a new enumerator each time. I mean, you could call Reset on the enumerator; but I'm pretty sure that's unsupported in like 90% of IEnumerator<T> implementations. So I guess you could get "unexpected" results, but only if you are expecting something that isn't feasible. In other words: for any ordered sequence (such as a T[], List<T>, Queue<T>, etc.), the order will be stable; for any unordered sequence, you shouldn't expect for it to be (in my opinion).

@Dan Tao 2010-09-05 23:45:30

@Gabe: An alternative, I suppose, would be to accept an optional bool parameter specifying whether the method should cache the order of the first enumeration and then loop over that.

@Gabe 2010-09-05 23:49:27

Dan: If you need the same results from the loop every time, you could just use x.Memoize().Loop(), but of course that means you need to have a Memoize function first. I agree that an optional bool would be fine, or a seperate method like LoopSame or LoopDeterministic.

@Dan Tao 2010-09-05 22:46:37

Parse

This one involves a custom delegate (could've used an IParser<T> interface instead, but I went with a delegate as it was simpler), which is used to parse a sequence of strings to a sequence of values, skipping the elements where parsing fails.

public delegate bool TryParser<T>(string text, out T value);

public static IEnumerable<T> Parse<T>(this IEnumerable<string> source,
                                      TryParser<T> parser)
{
    source.ThrowIfNull("source");
    parser.ThrowIfNull("parser");

    foreach (string str in source)
    {
        T value;
        if (parser(str, out value))
        {
            yield return value;
        }
    }
}

Usage:

var strings = new[] { "1", "2", "H3llo", "4", "five", "6", "se7en" };
var numbers = strings.Parse<int>(int.TryParse);

foreach (int x in numbers)
{
    Console.WriteLine(x);
}

Output:

1
2
4
6

Naming's tricky for this one. I'm not sure whether Parse is the best option (it is simple, at least), or if something like ParseWhereValid would be better.

@Nappy 2010-09-05 23:03:01

TryParse or ParseWhereValid would fit best imo. ;)

@Dan Tao 2010-09-05 23:47:03

@Nappy: Yeah, I like TryParse; my only concern there is that someone might expect for it to return a bool and populate an out IEnumerable<T> argument instead (only returning true if every item was parsed). Maybe ParseWhereValid is best.

@Gabe 2010-09-05 22:38:49

CountUpTo

static int CountUpTo<T>(this IEnumerable<T> source, int maxCount)
{
    if (maxCount == 0)
        return 0;

    var genericCollection = source as ICollection<T>; 
    if (genericCollection != null) 
        return Math.Min(maxCount, genericCollection.Count);

    var collection = source as ICollection; 
    if (collection != null)
        return Math.Min(maxCount, collection.Count);

    int count = 0;
    foreach (T item in source)
        if (++count >= maxCount)
            break;
    return count;
}

@Timwi 2011-09-22 14:08:22

This is semantically the same as collection.Take(maxCount).Count(), right?

@Gabe 2011-09-22 15:40:01

@Timwi: Yes, it's the same.

@Ani 2010-09-05 11:19:47

AssertCount

Efficiently determines if an an IEnumerable<T> contains at least / exactly / at most a certain number of elements.

public enum CountAssertion
{
    AtLeast,
    Exact,
    AtMost
}

/// <summary>
/// Asserts that the number of items in a sequence matching a specified predicate satisfies a specified CountAssertion.
/// </summary>
public static bool AssertCount<T>(this IEnumerable<T> source, int countToAssert, CountAssertion assertion, Func<T, bool> predicate)
{
    if (source == null)
        throw new ArgumentNullException("source");

    if (predicate == null)
        throw new ArgumentNullException("predicate");

    return source.Where(predicate).AssertCount(countToAssert, assertion);
}

/// <summary>
/// Asserts that the number of elements in a sequence satisfies a specified CountAssertion.
/// </summary>
public static bool AssertCount<T>(this IEnumerable<T> source, int countToAssert, CountAssertion assertion)
{
    if (source == null)
        throw new ArgumentNullException("source");

    if (countToAssert < 0)
        throw new ArgumentOutOfRangeException("countToAssert");    

    switch (assertion)
    {
        case CountAssertion.AtLeast:
            return AssertCountAtLeast(source, GetFastCount(source), countToAssert);

        case CountAssertion.Exact:
            return AssertCountExact(source, GetFastCount(source), countToAssert);

        case CountAssertion.AtMost:
            return AssertCountAtMost(source, GetFastCount(source), countToAssert);

        default:
            throw new ArgumentException("Unknown CountAssertion.", "assertion");
    }

}

private static int? GetFastCount<T>(IEnumerable<T> source)
{
    var genericCollection = source as ICollection<T>;
    if (genericCollection != null)
        return genericCollection.Count;

    var collection = source as ICollection;
    if (collection != null)
        return collection.Count;

    return null;
}

private static bool AssertCountAtMost<T>(IEnumerable<T> source, int? fastCount, int countToAssert)
{
    if (fastCount.HasValue)
        return fastCount.Value <= countToAssert;

    int countSoFar = 0;

    foreach (var item in source)
    {
        if (++countSoFar > countToAssert) return false;
    }

    return true;
}

private static bool AssertCountExact<T>(IEnumerable<T> source, int? fastCount, int countToAssert)
{
    if (fastCount.HasValue)
        return fastCount.Value == countToAssert;

    int countSoFar = 0;

    foreach (var item in source)
    {
        if (++countSoFar > countToAssert) return false;
    }

    return countSoFar == countToAssert;
}

private static bool AssertCountAtLeast<T>(IEnumerable<T> source, int? fastCount, int countToAssert)
{
    if (countToAssert == 0)
        return true;

    if (fastCount.HasValue)
        return fastCount.Value >= countToAssert;

    int countSoFar = 0;

    foreach (var item in source)
    {
        if (++countSoFar >= countToAssert) return true;
    }

    return false;
}

Usage:

var nums = new[] { 45, -4, 35, -12, 46, -98, 11 };
bool hasAtLeast3Positive = nums.AssertCount(3, CountAssertion.AtLeast, i => i > 0); //true
bool hasAtMost1Negative = nums.AssertCount(1, CountAssertion.AtMost, i => i < 0); //false
bool hasExactly2Negative = nums.AssertCount(2, CountAssertion.Exact, i => i < 0); //false

@Ani 2010-09-05 12:44:18

@Timwi: Unfortunately, if Enumerable.Count<T>() cannot determine the count that way, it will enumerate the entire sequence. This would defeat the point of this extension, which can quick-fail and quick-pass.

@Timwi 2010-09-05 12:47:58

@Ani: OK, fair point. I missed that.

@Gabe 2010-09-05 21:57:17

You should include something like CountAtMost so that I can change my action based on whether there are none, singlular, or plural elements without having to create 3 enumerators or count all the elements.

@Ani 2010-09-05 22:01:28

@Gabe: Sorry, but I didn't quite get that. There is a CountAssertion.AtMost. Or am I missing something?

@Gabe 2010-09-05 22:06:32

Ani: Say I have this: int c = foo.Count(); if (c == 0) {...} else if (c == 1) {...} else {...} That works, but is inefficient if foo is a large enumerable because it has to count the whole thing even though it can stop at 2. What I want is to be able to say c = foo.CountAtMost(2); -- you have all the logic, but you don't return the actual number.

@Nappy 2010-09-05 22:18:01

IMO your usage of predicate in the first overload does not make sense, because you only use it at as a where condition and not in your assertion functions.

@Nappy 2010-09-05 22:22:46

@Gabe You mean something like AssertTrue(foo.Take(x).Count() == x)?

@Ani 2010-09-05 22:24:34

@Nappy: The example usage should clarify the use of the predicate.

@Ani 2010-09-05 22:26:00

@Gabe: I understand. I would write your example as int c = foo.Take(3).Count(); if (c == 0) {...} else if (c == 1) {...} else You are right about the multiple enumerators, I suppose you are looking for an overload int GetCountUpto<T>(this IEnumerable<T> source, int countUpto); or something?

@Nappy 2010-09-05 22:26:49

@Ani: Whats wrong with bool hasExactly2Negative = nums.Where(i => i < 0).AssertCount(2, CountAssertion.Exact); //false ? ;)

@Ani 2010-09-05 22:29:31

@Nappy: Nothing is wrong with that, many LINQ extension methods provide overloads that do exactly that. Why, even Enumerable.Count, for instance: myEnumerable.Where(condn).Count() is the same as myEnumerable.Count(condn).

@Nappy 2010-09-05 22:42:11

@Ani: OK you convinced me, but, those methods like Any, Count, First etc, you mentioned, do never accept more than one parameter. They are just Where with another return type. Thereby they are not as difficult to read compared to your usage of such a condition.

@Gabe 2010-09-05 22:43:35

Ani: Yes, like foo.Take(3).Count(), only without multiple enumerations. See stackoverflow.com/questions/3645644/…

@Gabe 2010-09-05 22:44:58

BTW, I dislike the Assertion nomenclature because the word Assert to me implies that it throws an exception when its condition is false.

@Ani 2010-09-05 22:50:15

@Gabe: Agree with you about the nomenclature; couldn't come up with anything better. TestCount?

@Gabe 2010-09-05 23:13:04

Ani: I would probably have 3 different methods: CountIs, CountIsAtMost, and CountIsAtLeast.

@Dan Tao 2010-09-05 23:53:54

I'm with Gabe on the naming (I actually skimmed over this answer originally and posted an identical one because I assumed this one throw an exception -- I deleted it when I realized they were the same).

@Mashmagar 2010-09-05 19:58:00

IsEmpty

public static bool IsEmpty<T>(this IEnumerable<T> source)
{
    return !source.Any();
}

@Nappy 2010-09-05 20:10:52

This is built-in called Any.

@Bear Monkey 2010-09-05 23:05:55

+1 I'm not sure why this was down voted. To me source.IsEmpty() is clearer to read than !source.Any(). I always try to avoid using the ! operator where possible as in my opinion its easy to skip over it when quickly scanning code.

@Gabe 2010-09-06 03:43:21

mfj196: It was downvoted before I fixed it.

@nawfal 2014-01-27 09:54:26

None is a more analogous to Any, than IsEmpty.

@p.campbell 2010-09-05 17:29:02

WhereIf

Optional Where clause on IEnumerable and IQueryable. Avoids if statements when building predicates & lambdas for a query. Useful when you don't know at compile time whether a filter should apply.

public static IEnumerable<TSource> WhereIf<TSource>(
            this IEnumerable<TSource> source, bool condition,
            Func<TSource, bool> predicate)
{
    return condition ? source.Where(predicate) : source;
}

Useage:

var custs = Customers.WhereIf(someBool, x=>x.EyeColor=="Green");

LINQ WhereIf At ExtensionMethod.NET and borrowed from Andrew's blog.

@KeithS 2010-09-07 15:34:16

Interesting. You could use this to link checkboxes to filters in an AJAX-ish search results page; mySearchResults.WhereIf(chkShowOnlyUnapproved.Checked, x=>!x.IsApproved)

@Dan Tao 2010-09-05 18:01:23

Duplicates

Used in conjunction with a method like Ani's AssertCount method (I use one called CountAtLeast), it becomes very easy to find elements in a sequence that appear more than once:

public static IEnumerable<T> Duplicates<T, TKey>(this IEnumerable<T> source,
    Func<T, TKey> keySelector = null, IEqualityComparer<TKey> comparer = null)
{
    source.ThrowIfNull("source");
    keySelector = keySelector ?? new Func<T, TKey>(x => x);
    comparer = comparer ?? EqualityComparer<TKey>.Default;

    return source.GroupBy(keySelector, comparer)
        .Where(g => g.CountAtLeast(2))
        .SelectMany(g => g);
}

@Timwi 2010-09-05 21:14:49

I think you could write g.CountAtLeast(2) in “built-in” LINQ as g.Skip(1).Any().

@Dan Tao 2010-09-05 22:07:07

@Timwi: That's exactly how I wrote it ;) Several of the extension methods I use are really just very thin wrappers around functionality that could already be written concisely (another example: SkipNulls(), which is just Where(x => x != null)). I use them not because they do all that much extra but rather because I find they make code that much more readable (and wrapping a couple method calls into one where appropriate for code reuse is not so bad, anyway).

@Gabe 2010-09-05 23:15:59

Dan: SkipNulls<T>() is really just OfType<T>().

@Dan Tao 2010-09-05 23:41:17

@Gabe: You could make it OfType<T> or Where<T>; either way it's just a trivial wrapper. My point was just that the name SkipNulls makes it a bit more purposeful.

@Dan Tao 2010-09-05 17:20:43

RandomSample

Here's a simple function that's useful if you have a medium-large set of data (say, over 100 items) and you want to eyeball just a random sampling of it.

public static IEnumerable<T> RandomSample<T>(this IEnumerable<T> source,
                                             double percentage)
{
    source.ThrowIfNull("source");

    var r = new Random();
    return source.Where(x => (r.NextDouble() * 100.0) < percentage);
}

Usage:

List<DataPoint> data = GetData();

// Sample roughly 3% of the data
var sample = data.RandomSample(3.0);

// Verify results were correct for this sample
foreach (DataPoint point in sample)
{
    Console.WriteLine("{0} => {1}", point, DoCalculation(point));
}

Notes:

  1. Not really appropriate for tiny collections as the number of items returned is probabilistic (could easily return zero on a small sequence).
  2. Not really appropriate for huge collections or database queries as it involves enumerating over every item in the sequence.

@mattmc3 2010-09-05 22:28:28

Interesting, though it's generally more useful to ask for X random elements, rather than to say "give me approximately X% of the elements randomly". To do that, you should do something like this: source.OrderBy(r.NextDouble()).Take(x);

@Nappy 2010-09-05 15:02:42

ZipMerge

This is my version of Zip which works like a real zipper. It does not project two values into one but returns a combined IEnumerable. Overloads, skipping the right and/or left tail are possible.

public static IEnumerable<TSource> ZipMerge<TSource>(
        this IEnumerable<TSource> first,
        IEnumerable<TSource> second)
{
    using (var secondEnumerator = second.GetEnumerator())
    {
        foreach (var item in first)
        {
            yield return item;

            if (secondEnumerator.MoveNext())
                yield return secondEnumerator.Current;
        }

        while (secondEnumerator.MoveNext())
            yield return secondEnumerator.Current;
    }
}

@Timwi 2010-09-05 21:17:08

Useful, but should perhaps be called something else than the built-in Zip? (I know the parameters are enough to distinguish, but in the interest of readability of code...)

@Nappy 2010-09-05 21:33:01

@Timwi Any suggestions for another name? Maybe ZipMerge?

@Timwi 2010-09-05 21:43:37

Yeah, sounds good. Edited.

@Aistina 2010-09-06 08:06:46

Wouldn't this skip the first element of second, or am I misreading the code?

@Nappy 2010-09-06 08:19:59

@Aistina: I think you have a misunderstanding of MoveNext. The first call tells you whether the enumerator is empty or not. Current contains then the first element.

@Aistina 2010-09-06 08:38:02

@Nappy: I see, thanks for enlightening me! :)

@realbart 2016-12-07 09:15:32

MoveNext beyond the limit of an enumerator throws an exception, so if the secondEnumerator is more than one element smaller than the second, this yields an exception

@Nappy 2016-12-07 11:08:30

@realbart Thats not true: "If MoveNext passes the end of the collection, the enumerator is positioned after the last element in the collection and MoveNext returns false. When the enumerator is at this position, subsequent calls to MoveNext also return false until Reset is called." See msdn.microsoft.com/library/…

@realbart 2016-12-07 12:19:11

My bad. I guess something else went wrong when I used this myself.

@Handcraftsman 2010-09-05 16:27:58

String.Join for IEnumerable<T>

    public static string Join<T>(this IEnumerable<T> items, string delimiter)
    {
        var result = new StringBuilder();
        if (items != null && items.Any())
        {
            delimiter = delimiter ?? String.Empty;
            foreach (var item in items)
            {
                result.Append(item);
                result.Append(delimiter);
            }
            result.Length = result.Length - delimiter.Length;
        }
        return result.ToString();
    }

@Nappy 2010-09-05 16:43:09

This is almost identical to JoinString.

@Ian Mercer 2010-09-05 23:12:37

String.Join in .NET 4 takes IEnumerable<T>

Related Questions

Sponsored Content

10 Answered Questions

[SOLVED] IEnumerable vs List - What to Use? How do they work?

296 Answered Questions

[SOLVED] Hidden Features of C#?

  • 2008-08-12 16:32:24
  • Serhat Ozgel
  • 662552 View
  • 1476 Score
  • 296 Answer
  • Tags:   c# hidden-features

25 Answered Questions

[SOLVED] Why not inherit from List<T>?

18 Answered Questions

[SOLVED] Distinct() with lambda?

9 Answered Questions

[SOLVED] Learning about LINQ

17 Answered Questions

[SOLVED] Type or namespace name does not exist

10 Answered Questions

[SOLVED] Sorting a list using Lambda/Linq to objects

1 Answered Questions

[SOLVED] Multiple Order By with LINQ

  • 2010-02-23 14:35:13
  • sdanna
  • 154107 View
  • 206 Score
  • 1 Answer
  • Tags:   c# linq lambda

150 Answered Questions

2 Answered Questions

[SOLVED] Where is the "Fold" LINQ Extension Method?

Sponsored Content