71

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.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Nappy
  • 3,016
  • 27
  • 39

43 Answers43

33

Append & Prepend

(These have been added to .NET since this answer was written.)

/// <summary>Adds a single element to the end of an IEnumerable.</summary>
/// <typeparam name="T">Type of enumerable to return.</typeparam>
/// <returns>IEnumerable containing all the input elements, followed by the
/// specified additional element.</returns>
public static IEnumerable<T> Append<T>(this IEnumerable<T> source, T element)
{
    if (source == null)
        throw new ArgumentNullException("source");
    return concatIterator(element, source, false);
}

/// <summary>Adds a single element to the start of an IEnumerable.</summary>
/// <typeparam name="T">Type of enumerable to return.</typeparam>
/// <returns>IEnumerable containing the specified additional element, followed by
/// all the input elements.</returns>
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> tail, T head)
{
    if (tail == null)
        throw new ArgumentNullException("tail");
    return concatIterator(head, tail, true);
}

private static IEnumerable<T> concatIterator<T>(T extraElement,
    IEnumerable<T> source, bool insertAtStart)
{
    if (insertAtStart)
        yield return extraElement;
    foreach (var e in source)
        yield return e;
    if (!insertAtStart)
        yield return extraElement;
}
Timwi
  • 65,159
  • 33
  • 165
  • 230
  • You could probably generalize even more by adding an enum for where to place the value, and then adding "between". I had the need to inject a value inbetween all values in a collection, sort of like String.Join type of functionality, only with generics. – Lasse V. Karlsen Sep 05 '10 at 10:30
  • @Lasse V. Karlsen: I’ve [posted an InsertBetween method](http://stackoverflow.com/questions/3645644/whats-your-favorite-linq-to-objects-operator-which-is-not-built-in/3645810#3645810) as a separate answer. – Timwi Sep 05 '10 at 10:56
  • 7
    You can shorten the 'Append` implementation to a one liner: `return source.Concat(Enumerable.Repeat(element, 1));`. – Steven Sep 05 '10 at 10:59
  • 16
    Append and Prepend could also be implemented with [AsEnumerable](http://stackoverflow.com/questions/3645644/whats-your-favorite-linq-to-objects-operator-which-is-not-built-in/3645819#3645819): `head.AsEnumerable().Concat(source)` / `source.Concat(element.AsEnumerable())` – Nappy Sep 05 '10 at 12:43
  • Beware of the yield return statement. If you use `Append()` or `Prepend()` on a `Serializable` collection, the result of the Append or Prepend will NOT be `Serializable`: http://stackoverflow.com/questions/3294224/c-serialization-and-the-yield-statement – Carlos Muñoz Sep 05 '10 at 17:47
  • @Carlos Muñoz: Nor will anything else posted on this page. So what? – Timwi Sep 05 '10 at 21:04
  • It means exactly that. For example in ASP.NET if you want to store the `IEnumerable` in the `Session` object and you are using other mechanism than InProc (StateServer or SQLServer) then your IEnumerable must be `Serializable`. Some people don't realize that and it could be a problem if they are not aware of that. – Carlos Muñoz Sep 05 '10 at 21:32
  • @Carlos Muñoz: Fair enough, but that has nothing to do with `yield` or with this post: the same is true of any of the built-in extension methods like `Where` and `Select`. – Timwi Sep 05 '10 at 21:40
  • Be aware of, that this will be very slow if you use Append to add elements often. IEnumerable is not designed for this. If you use this to build a IEnumerable with n elements, then you would end up with calling n methods deep at the end. I guess that yields to O(n^2) (1 calls, 2 calls, ..., n calls). Correct me, if I'm wrong. Instead a linked list or a regular list (based on arrays) would be much better - both O(1) (amortized for arrays) for inserts, and O(n) for iteration:) – Lasse Espeholt Sep 28 '10 at 08:51
  • @lasseespeholt: Of course that is correct. It is still useful for people who use it responsibly though. (Some food for thought: changing any sensible O(n) recursive algorithm (e.g. a simple tree walk) into one that uses `yield return` for each recursive invocation turns it into an O(n²) number of method calls, too.) – Timwi Sep 28 '10 at 13:39
  • 2
    Good one +1 but I'd change it from T to `params T[]` so that you can append one or more items to the end. –  Jun 17 '11 at 16:08
  • Just note: Append and Prepend exist since .Net Standard 1.6. – Ender Look Feb 24 '20 at 22:52
21

I'm surprised no one has mentioned the MoreLINQ project yet. It was started by Jon Skeet and has gained some developers along the way. From the project's page:

LINQ to Objects is missing a few desirable features.

This project will enhance LINQ to Objects with extra methods, in a manner which keeps to the spirit of LINQ.

Take a look at the Operators Overview wiki page for a list of implemented operators.

It is certainly a good way to learn from some clean and elegant source code.

Community
  • 1
  • 1
Ahmad Mageed
  • 94,561
  • 19
  • 163
  • 174
16

Each

Nothing for the purists, but darn it's useful!

 public static void Each<T>(this IEnumerable<T> items, Action<T> action)
 {
   foreach (var i in items)
      action(i);
 }
flq
  • 22,247
  • 8
  • 55
  • 77
  • 3
    Parallel.ForEach would be doing the same and capable of parallel execution. Isnt it.. – abhishek Sep 05 '10 at 10:01
  • 1
    An overload taking a func instead of an action and yield return the results would be obvious too. – Nappy Sep 05 '10 at 10:09
  • 25
    @Nappy: That one’s called `Select` and it’s built in. – Timwi Sep 05 '10 at 10:15
  • It's nice that Parallel.ForEach is available now, but it isn't really the same, is it? I hope you haven't planned to replace every single forach loop in your code with the Parallel version? – flq Sep 05 '10 at 10:19
  • +1 Can it be true that this functionality was included in a earlier release? I've looked after it many times because I think it was... – Lasse Espeholt Sep 05 '10 at 10:19
  • @lasseespeholt: There is `List.ForEach` and `Array.ForEach`, but nothing equivalent for `IEnumerable`... – Timwi Sep 05 '10 at 10:24
  • 1
    Its part of the System.Interactive.dll of the Reactive Extensions for .NET (Rx) called Do: "Invokes the action for its side-effects on each value in the sequence." – Nappy Sep 05 '10 at 10:42
  • I'm in two minds about this. On the one hand, it's good for API consistency (there's a parallel version, so how about a non-parallel version too). On the other hand, a functional API should not be used for something that's inherently non-functional in nature. – Christian Hayter Sep 05 '10 at 11:07
  • 1
    I would return the original list to allow for method chaining. – Zebi Sep 05 '10 at 13:40
  • 2
    @Nappy: Do is not the equivalent of the method in the example; it would have to be followed by Run(), which also has an overload which takes an Action. The latter would be the equivalent of the example. – Markus Johnsson Sep 05 '10 at 13:47
  • @Markus Johnsson Sorry, you are right, thanks for pointing that out. I also noted this, but it depends on the usage intend whether to use .Do or .Run. – Nappy Sep 05 '10 at 14:09
  • 1
    @Zebi: Practically, that's a great idea. Logically, it may be a bit confusing. @abishek: There are some of us still working in .NET 3.5, thank you very much. – KeithS Sep 07 '10 at 15:42
14

ToQueue & ToStack

/// <summary>Creates a <see cref="Queue&lt;T&gt;"/> from an enumerable
/// collection.</summary>
public static Queue<T> ToQueue<T>(this IEnumerable<T> source)
{
    if (source == null)
        throw new ArgumentNullException("source");
    return new Queue<T>(source);
}

/// <summary>Creates a <see cref="Stack&lt;T&gt;"/> from an enumerable
/// collection.</summary>
public static Stack<T> ToStack<T>(this IEnumerable<T> source)
{
    if (source == null)
        throw new ArgumentNullException("source");
    return new Stack<T>(source);
}
Timwi
  • 65,159
  • 33
  • 165
  • 230
  • What's wrong with just `var myQueue = new Queue(myObj);`? For only one-line, this isn't really a worthwhile extension... – cjk Sep 06 '10 at 07:35
  • 2
    @ck: You could apply the same logic to the built-in extension `ToList()` and these extensions also complement the `ToArray()` extension nicely. I prefer the fluent `var myQueue = a.SelectMany(...).Where(...).OrderBy(...).ToQueue()` to the more traditional syntax. – Martin Liversage Sep 06 '10 at 11:31
  • 1
    @Martin (&TimwI) - I can see the point when chaining together a large number of operators, it is *much* more tidy that way. +1. – cjk Sep 06 '10 at 11:36
  • 2
    @cjk the biggest advantage I see is the type parameter is not being specified. I wouldn't want to write `` there if compiler can infer it. – nawfal Jul 10 '14 at 18:52
13

IsEmpty

public static bool IsEmpty<T>(this IEnumerable<T> source)
{
    return !source.Any();
}
Gabe
  • 84,912
  • 12
  • 139
  • 238
Mashmagar
  • 2,556
  • 2
  • 29
  • 38
  • 6
    +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. – Bear Monkey Sep 05 '10 at 23:05
  • 3
    `None` is a more analogous to `Any`, than `IsEmpty`. – nawfal Jan 27 '14 at 09:54
12

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;
}
Johann Blais
  • 9,389
  • 6
  • 45
  • 65
  • Instead of `if (values == null) return false;` I think it should throw an exception. Silently swallowing error conditions is never good. – Timwi Sep 07 '10 at 02:40
  • It depends on how you look at it. The fact is an element is never contained in an empty list of values. – Johann Blais Sep 07 '10 at 06:50
  • 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. – KeithS Mar 30 '12 at 16:50
  • 1
    Just `return values.Contains(value);` is enough. – nawfal Jan 27 '14 at 09:57
9

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();
    }
}
Michael Sorens
  • 35,361
  • 26
  • 116
  • 172
Timwi
  • 65,159
  • 33
  • 165
  • 230
  • 1
    Very useful, although personally I would take out all the formatting code and just have the ability to join `IEnumerable` with a separator. You can always project the data to `IEnumerable` before calling this method. – Christian Hayter Sep 05 '10 at 11:11
  • @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`. – Ani Sep 05 '10 at 14:46
  • @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. – Timwi Sep 05 '10 at 16:19
  • 4
    String.Join in .NET 4 takes an IEnumerable. – Ian Mercer Sep 05 '10 at 23:07
  • 1
    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. – Kirk Broadhurst Sep 12 '10 at 13:52
  • 1
    @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. – Timwi Sep 12 '10 at 19:05
9

AsIEnumerable

/// <summary>
/// Returns a sequence containing one element.
/// </summary>
public static IEnumerable<T> AsIEnumerable<T>(this T obj)
{
    yield return obj;
}  

Usage:

var nums = new[] {12, 20, 6};
var numsWith5Prepended = 5.AsIEnumerable().Concat(nums);   
Timwi
  • 65,159
  • 33
  • 165
  • 230
Ani
  • 111,048
  • 26
  • 262
  • 307
  • Some kind of a linked list would definitely be better. `yield return x` will construct a whole new `IEnumerable`. So don't use it for concatenating many items. – Lasse Espeholt Sep 05 '10 at 11:05
  • 2
    I favor to write EnumerableEx.Return(5).Concat(nums) instead of bloating any objects IntelliSense. – Nappy Sep 05 '10 at 11:15
  • 2
    I prefer using [`Append` and `Prepend`](http://stackoverflow.com/questions/3645644/whats-your-favorite-linq-to-objects-operator-which-is-not-built-in/3645715#3645715) for this. – Timwi Sep 05 '10 at 12:35
  • I haven't checked myself, but I think the latest release of Rx contains a bunch of overloads on this pattern, that is: extension methods that return an IEnumerable with a single item in it. – Markus Johnsson Sep 05 '10 at 13:58
  • 14
    Purely for performance, I would suggest `return new T[] { obj };` instead. That way, the compiler doesn't have to construct a whole state machine class just to yield one value. – Christian Hayter Sep 05 '10 at 16:46
  • @Timwi: For `Append`, I'm with you. For `Prepend`, it seems awkward to have the *first* item in the sequence come after the sequence to be prepended to in the method chain. My way would be to use your `Append` as-is and then change `Prepend` to actually just be an overload of `Append` that takes its arguments in the opposite order (so you could write: `1.Append(new int[] { 2, 3, 4 })`). – Dan Tao Sep 05 '10 at 22:23
  • 4
    I find this implementation dangerous. What would you expect from `new[]{1, 2, 3, 4}.AsIEnumerable()`? I would expect 1,2,3,4, not [1,2,3,4]. – larsmoa Jul 12 '11 at 09:37
  • @Timwi: There are other useful cases (beyond appending and prepending) for this. For example if its used inside an if-else-clause nested in SelectMany selector. – Nappy Jul 12 '11 at 15:07
  • 1
    @larsm: This is why most libraries use `EnumerableEx.Return(new[]{1, 2, 3, 4})`. You are right, the "As" implies there is some casting going on, and because an array already implements IEnumerable your expect nothing to change. – Nappy Jul 12 '11 at 15:13
  • I call it `Yield`. Not confusing to me. – nawfal Jul 10 '14 at 18:58
8

Order

/// <summary>Sorts the elements of a sequence in ascending order.</summary>
public static IEnumerable<T> Order<T>(this IEnumerable<T> source)
{
    return source.OrderBy(x => x);
}
Timwi
  • 65,159
  • 33
  • 165
  • 230
8

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--;
    }
}
Handcraftsman
  • 6,863
  • 2
  • 40
  • 33
  • I would propose to rename this to either Randomize or Shuffle. – Nappy Sep 05 '10 at 19:52
  • This might be better with a static Random object. – cjk Sep 06 '10 at 07:40
  • Rather than using Random, you could just order using new GUID values - items.OrderBy(x => Guid.NewGuid()). – Scott Mitchell Sep 10 '10 at 20:08
  • @Scott guids are unique but are not guaranteed to be random. See: http://stackoverflow.com/questions/467271/how-random-is-system-guid-newguid – Handcraftsman Sep 11 '10 at 14:11
  • 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: http://stackoverflow.com/questions/1651619/optimal-linq-query-to-get-a-random-sub-collection-shuffle/1653204#1653204 – LukeH Sep 13 '10 at 00:14
  • @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 http://www.4guysfromrolla.com/articles/070208-1.aspx. (Also, to be pedantic, the Random class isn't truly random, either. ) – Scott Mitchell Sep 13 '10 at 17:10
  • 2
    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). – Craig Gidney Sep 25 '10 at 05:37
  • 2
    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. – Nappy Jul 12 '11 at 15:00
  • 1
    @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` but someone has to do the work of simplifying the way that the method gets its PRNs. – KeithS Aug 11 '15 at 17:10
7

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;
    }
}
Timwi
  • 65,159
  • 33
  • 165
  • 230
  • 1
    It would be much preferable to either make `valueSelector` return an `IComparable` or change `valueSelector` to something like `Func lessThan` so that things like strings or decimals could be compared. – Gabe Sep 05 '10 at 22:22
7

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.

Dan Tao
  • 125,917
  • 54
  • 300
  • 447
  • This implementation has the interesting property that it creates a new enumerator each time through, so it could give unexpected results. – Gabe Sep 05 '10 at 23:18
  • @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` 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`, `Queue`, etc.), the order will be stable; for any unordered sequence, you shouldn't expect for it to be (in my opinion). – Dan Tao Sep 05 '10 at 23:43
  • @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. – Dan Tao Sep 05 '10 at 23:45
  • 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`. – Gabe Sep 05 '10 at 23:49
6

IndexOf

/// <summary>
/// Returns the index of the first element in this <paramref name="source"/>
/// satisfying the specified <paramref name="condition"/>. If no such elements
/// are found, returns -1.
/// </summary>
public static int IndexOf<T>(this IEnumerable<T> source, Func<T, bool> condition)
{
    if (source == null)
        throw new ArgumentNullException("source");
    if (condition == null)
        throw new ArgumentNullException("condition");
    int index = 0;
    foreach (var v in source)
    {
        if (condition(v))
            return index;
        index++;
    }
    return -1;
}
Timwi
  • 65,159
  • 33
  • 165
  • 230
  • 5
    You should call this `FindIndex` to match the method on `List` and `Array` that does the same thing. I would also consider checking to see if `source` is one of those things that already implements it and calling the native `FindIndex` function (although that won't make much of a difference performance-wise because you don't have an overload that takes a starting index). – Gabe Sep 05 '10 at 21:42
6

Chunks

Returns chunks of a specific size. x.Chunks(2) of 1,2,3,4,5 will return two arrays with 1,2 and 3,4. x.Chunks(2,true) will return 1,2, 3,4 and 5.

public static IEnumerable<T[]> Chunks<T>(this IEnumerable<T> xs, int size, bool returnRest = false)
{
    var curr = new T[size];

    int i = 0;

    foreach (var x in xs)
    {
        if (i == size)
        {
            yield return curr;
            i = 0;
            curr = new T[size];
        }

        curr[i++] = x;
    }

    if (returnRest)
        yield return curr.Take(i).ToArray();
}
Lasse Espeholt
  • 17,622
  • 5
  • 63
  • 99
  • @Timwi Thanks for pointing that out. I usually use one which returns Lists, but I altered it to return arrays which I think most what. Correcting it now :) – Lasse Espeholt Sep 05 '10 at 10:57
  • An alternative name would be `Buffer` – Nappy Sep 05 '10 at 12:21
  • Why do you return an array? I would prefer IEnumerable> – Nappy Sep 05 '10 at 13:03
  • 2
    @Nappy: [It *is* an `IEnumerable>`](http://msdn.microsoft.com/en-us/library/dd233059.aspx). – Timwi Sep 05 '10 at 13:10
  • @Nappy A pure `IEnumerable` version would be slower (at least for small chunks). But as mentioned, I've used many versions of the above. And you can always use the array as a `IEnumerable` if you like because arrays inherit `IEnumerable`. – Lasse Espeholt Sep 05 '10 at 13:11
  • @Timwi Thanks for reminding me about the covariant/contravariant feature. I just wanted to make sure we remain inside the monad ;) – Nappy Sep 05 '10 at 13:28
  • @LasseEspeholt- I agree; not only are arrays IEnumerable, but if you're using this method, you're passing it a literal or variable that defines the length of each chunk, so you should be able to stay within the bounds of the array. – KeithS Mar 29 '17 at 16:12
6

ToHashSet

public static HashSet<T> ToHashSet<T>(this IEnumerable<T> items)
{
    return new HashSet<T>(items);
}
Nappy
  • 3,016
  • 27
  • 39
Handcraftsman
  • 6,863
  • 2
  • 40
  • 33
5

FirstOrDefault with a default value specified

/// <summary>
/// Returns the first element of a sequence, or a default value if the
/// sequence contains no elements.
/// </summary>
/// <typeparam name="T">The type of the elements of
/// <paramref name="source"/>.</typeparam>
/// <param name="source">The <see cref="IEnumerable&lt;T&gt;"/> to return
/// the first element of.</param>
/// <param name="default">The default value to return if the sequence contains
/// no elements.</param>
/// <returns><paramref name="default"/> if <paramref name="source"/> is empty;
/// otherwise, the first element in <paramref name="source"/>.</returns>
public static T FirstOrDefault<T>(this IEnumerable<T> source, T @default)
{
    if (source == null)
        throw new ArgumentNullException("source");
    using (var e = source.GetEnumerator())
    {
        if (!e.MoveNext())
            return @default;
        return e.Current;
    }
}

/// <summary>
/// Returns the first element of a sequence, or a default value if the sequence
/// contains no elements.
/// </summary>
/// <typeparam name="T">The type of the elements of
/// <paramref name="source"/>.</typeparam>
/// <param name="source">The <see cref="IEnumerable&lt;T&gt;"/> to return
/// the first element of.</param>
/// <param name="predicate">A function to test each element for a
/// condition.</param>
/// <param name="default">The default value to return if the sequence contains
/// no elements.</param>
/// <returns><paramref name="default"/> if <paramref name="source"/> is empty
/// or if no element passes the test specified by <paramref name="predicate"/>;
/// otherwise, the first element in <paramref name="source"/> that passes
/// the test specified by <paramref name="predicate"/>.</returns>
public static T FirstOrDefault<T>(this IEnumerable<T> source,
    Func<T, bool> predicate, T @default)
{
    if (source == null)
        throw new ArgumentNullException("source");
    if (predicate == null)
        throw new ArgumentNullException("predicate");
    using (var e = source.GetEnumerator())
    {
        while (true)
        {
            if (!e.MoveNext())
                return @default;
            if (predicate(e.Current))
                return e.Current;
        }
    }
}
Timwi
  • 65,159
  • 33
  • 165
  • 230
5

InsertBetween

Inserts an element in between every pair of consecutive elements.

/// <summary>Inserts the specified item in between each element in the input
/// collection.</summary>
/// <param name="source">The input collection.</param>
/// <param name="extraElement">The element to insert between each consecutive
/// pair of elements in the input collection.</param>
/// <returns>A collection containing the original collection with the extra
/// element inserted. For example, new[] { 1, 2, 3 }.InsertBetween(0) returns
/// { 1, 0, 2, 0, 3 }.</returns>
public static IEnumerable<T> InsertBetween<T>(
    this IEnumerable<T> source, T extraElement)
{
    return source.SelectMany(val => new[] { extraElement, val }).Skip(1);
}
Timwi
  • 65,159
  • 33
  • 165
  • 230
5

EmptyIfNull

This is a controversial one; I am sure many purists will object to an "instance method" on null succeeding.

/// <summary>
/// Returns an IEnumerable<T> as is, or an empty IEnumerable<T> if it is null
/// </summary>
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source)
{
    return source ?? Enumerable.Empty<T>();
}    

Usage:

foreach(var item in myEnumerable.EmptyIfNull())
{
  Console.WriteLine(item);   
}
Ani
  • 111,048
  • 26
  • 262
  • 307
5

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.

Dan Tao
  • 125,917
  • 54
  • 300
  • 447
  • 1
    `TryParse` or `ParseWhereValid ` would fit best imo. ;) – Nappy Sep 05 '10 at 23:03
  • 2
    @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` argument instead (only returning true if *every* item was parsed). Maybe `ParseWhereValid` is best. – Dan Tao Sep 05 '10 at 23:47
4

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
  • 111,048
  • 26
  • 262
  • 307
  • @Timwi: Unfortunately, if `Enumerable.Count()` 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. – Ani Sep 05 '10 at 12:44
  • 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. – Gabe Sep 05 '10 at 21:57
  • @Gabe: Sorry, but I didn't quite get that. There is a `CountAssertion.AtMost`. Or am I missing something? – Ani Sep 05 '10 at 22:01
  • 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. – Gabe Sep 05 '10 at 22:06
  • 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 Sep 05 '10 at 22:18
  • @Gabe You mean something like AssertTrue(foo.Take(x).Count() == x)? – Nappy Sep 05 '10 at 22:22
  • @Nappy: The example usage should clarify the use of the predicate. – Ani Sep 05 '10 at 22:24
  • @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(this IEnumerable source, int countUpto);` or something? – Ani Sep 05 '10 at 22:26
  • @Ani: Whats wrong with `bool hasExactly2Negative = nums.Where(i => i < 0).AssertCount(2, CountAssertion.Exact); //false` ? ;) – Nappy Sep 05 '10 at 22:26
  • @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)`. – Ani Sep 05 '10 at 22:29
  • @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. – Nappy Sep 05 '10 at 22:42
  • Ani: Yes, like `foo.Take(3).Count()`, only without multiple enumerations. See http://stackoverflow.com/questions/3645644/whats-your-favorite-linq-to-objects-operator-which-is-not-built-in/3648107#3648107 – Gabe Sep 05 '10 at 22:43
  • 1
    BTW, I dislike the `Assertion` nomenclature because the word `Assert` to me implies that it throws an exception when its condition is false. – Gabe Sep 05 '10 at 22:44
  • @Gabe: Agree with you about the nomenclature; couldn't come up with anything better. TestCount? – Ani Sep 05 '10 at 22:50
  • 2
    Ani: I would probably have 3 different methods: `CountIs`, `CountIsAtMost`, and `CountIsAtLeast`. – Gabe Sep 05 '10 at 23:13
  • 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). – Dan Tao Sep 05 '10 at 23:53
4

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
  • 65,159
  • 33
  • 165
  • 230
Nappy
  • 3,016
  • 27
  • 39
  • 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...) – Timwi Sep 05 '10 at 21:17
  • @Timwi Any suggestions for another name? Maybe ZipMerge? – Nappy Sep 05 '10 at 21:33
  • Wouldn't this skip the first element of `second`, or am I misreading the code? – Aistina Sep 06 '10 at 08:06
  • @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. – Nappy Sep 06 '10 at 08:19
  • 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 – realbart Dec 07 '16 at 09:15
  • 1
    @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 https://msdn.microsoft.com/library/system.collections.ienumerator.movenext.aspx – Nappy Dec 07 '16 at 11:08
  • My bad. I guess something else went wrong when I used this myself. – realbart Dec 07 '16 at 12:19
4

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.
Timwi
  • 65,159
  • 33
  • 165
  • 230
Dan Tao
  • 125,917
  • 54
  • 300
  • 447
  • 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);` – mattmc3 Sep 05 '10 at 22:28
4

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();
}
Timwi
  • 65,159
  • 33
  • 165
  • 230
noopman
  • 660
  • 1
  • 4
  • 15
  • Do not forget to wrap enumerator in a using statement. – Bear Monkey Sep 06 '10 at 12:20
  • 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. – Timwi Sep 07 '10 at 02:52
  • 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. – noopman Sep 07 '10 at 05:11
  • 1
    +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. – Bear Monkey Sep 23 '10 at 08:27
  • I kind of agree but still. .AnyAtAll() is in reference to .Any() which throws on null. – noopman Sep 28 '10 at 07:13
  • 1
    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. – KeithS Aug 11 '15 at 17:16
4

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();
    }
}
Nappy
  • 3,016
  • 27
  • 39
3

SkipLast & TakeLast

/// <summary>
/// Enumerates the items of this collection, skipping the last
/// <paramref name="count"/> items. Note that the memory usage of this method
/// is proportional to <paramref name="count"/>, but the source collection is
/// only enumerated once, and in a lazy fashion. Also, enumerating the first
/// item will take longer than enumerating subsequent items.
/// </summary>
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source, int count)
{
    if (source == null)
        throw new ArgumentNullException("source");
    if (count < 0)
        throw new ArgumentOutOfRangeException("count",
            "count cannot be negative.");
    if (count == 0)
        return source;
    return skipLastIterator(source, count);
}
private static IEnumerable<T> skipLastIterator<T>(IEnumerable<T> source,
    int count)
{
    var queue = new T[count];
    int headtail = 0; // tail while we're still collecting, both head & tail
                      // afterwards because the queue becomes completely full
    int collected = 0;

    foreach (var item in source)
    {
        if (collected < count)
        {
            queue[headtail] = item;
            headtail++;
            collected++;
        }
        else
        {
            if (headtail == count) headtail = 0;
            yield return queue[headtail];
            queue[headtail] = item;
            headtail++;
        }
    }
}

/// <summary>
/// Returns a collection containing only the last <paramref name="count"/>
/// items of the input collection. This method enumerates the entire
/// collection to the end once before returning. Note also that the memory
/// usage of this method is proportional to <paramref name="count"/>.
/// </summary>
public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int count)
{
    if (source == null)
        throw new ArgumentNullException("source");
    if (count < 0)
        throw new ArgumentOutOfRangeException("count",
            "count cannot be negative.");
    if (count == 0)
        return new T[0];

    var queue = new Queue<T>(count + 1);
    foreach (var item in source)
    {
        if (queue.Count == count)
            queue.Dequeue();
        queue.Enqueue(item);
    }
    return queue.AsEnumerable();
}
Timwi
  • 65,159
  • 33
  • 165
  • 230
  • I believe your implementation of `TakeLast` could be used for `SkipLast`, with `yield return queue.Dequeue();`. – Mark Hurd May 24 '16 at 13:01
3

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.

Timwi
  • 65,159
  • 33
  • 165
  • 230
p.campbell
  • 98,673
  • 67
  • 256
  • 322
  • Interesting. You could use this to link checkboxes to filters in an AJAX-ish search results page; `mySearchResults.WhereIf(chkShowOnlyUnapproved.Checked, x=>!x.IsApproved)` – KeithS Sep 07 '10 at 15:34
3

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);
}
Community
  • 1
  • 1
Dan Tao
  • 125,917
  • 54
  • 300
  • 447
  • I think you could write `g.CountAtLeast(2)` in “built-in” LINQ as `g.Skip(1).Any()`. – Timwi Sep 05 '10 at 21:14
  • @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). – Dan Tao Sep 05 '10 at 22:07
  • Dan: `SkipNulls()` is really just `OfType()`. – Gabe Sep 05 '10 at 23:15
  • @Gabe: You could make it `OfType` or `Where`; either way it's just a trivial wrapper. My point was just that the name `SkipNulls` makes it a bit more purposeful. – Dan Tao Sep 05 '10 at 23:41
3

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;
}
Bear Monkey
  • 513
  • 2
  • 9
2

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;
}
Gabe
  • 84,912
  • 12
  • 139
  • 238
2

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
}
mattmc3
  • 17,595
  • 7
  • 83
  • 103
  • Since you're actually using it, allow me to simplify it for you. – Gabe Sep 05 '10 at 23:20
  • No thanks. As your version only works with object types (not DateTime, etc.) and your usage of OfType 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. – mattmc3 Sep 06 '10 at 00:00
  • But OfType does work with DateTime, no?. Also, I do think of OfType as a non-null filtering method, how else would it work? Maybe its just me and Gabe... – Bear Monkey Sep 06 '10 at 00:36
  • 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 (http://msdn.microsoft.com/en-us/library/bb360913.aspx). The MSDN article doesn't even mention filtering out nulls. – mattmc3 Sep 06 '10 at 00:57
  • Made classic mistake when converting from VB to C#... `Nothing` is not equivalent to `null`... had to revise C# implementation. – mattmc3 Sep 06 '10 at 01:48
  • @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 Sep 07 '10 at 15:34
  • @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. – mattmc3 Sep 08 '10 at 12:42
2

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));
Nevermind
  • 1,521
  • 1
  • 15
  • 16
1

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;
    }
}
Gabe
  • 84,912
  • 12
  • 139
  • 238
  • Isn't this the same as FirstOrDefault(): http://msdn.microsoft.com/en-us/library/bb358452.aspx – M4N Sep 26 '10 at 09:51
  • M4N: No, `FirstOrDefault` doesn't call `MoveNext` a second time. – Gabe Sep 26 '10 at 15:01
  • @Gabe what's the point of calling or not `MoveNext()` a second time? Can you tell a practical use case for `OneOrDefault`? Thanks. – Stéphane Gourichon Aug 11 '15 at 14:03
  • 1
    @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`. – Gabe Sep 11 '15 at 05:04
1

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
                });                      
        }
    }
}
Ryan Clarke
  • 197
  • 2
  • 11
Omer Raviv
  • 11,409
  • 5
  • 43
  • 82
1

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.

KeithS
  • 70,210
  • 21
  • 112
  • 164
1

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.

KeithS
  • 70,210
  • 21
  • 112
  • 164
  • Why the asymmetry between ties? – Stéphane Gourichon Aug 11 '15 at 14:10
  • @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 Aug 11 '15 at 17:02
0
/// <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);
    }
}
Salar
  • 2,088
  • 21
  • 26
0

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)));
    }
Timwi
  • 65,159
  • 33
  • 165
  • 230
dkackman
  • 15,179
  • 13
  • 69
  • 123
0

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;
}
Johann Blais
  • 9,389
  • 6
  • 45
  • 65
  • Not relevant to the question, which is about `IEnumerable`. – Timwi Sep 07 '10 at 02:53
  • 1
    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. – Johann Blais Sep 07 '10 at 06:48
0
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);
   }
  }
John Egbert
  • 5,496
  • 8
  • 32
  • 44
0

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;
}
Mike
  • 1,274
  • 10
  • 24
0

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.

leviathanbadger
  • 1,682
  • 15
  • 23
  • 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. – Nappy Jan 16 '12 at 16:38
-1

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
  • 3,016
  • 27
  • 39
Handcraftsman
  • 6,863
  • 2
  • 40
  • 33
  • This is almost identical to [JoinString](http://stackoverflow.com/questions/3645644/whats-your-favorite-linq-to-objects-operator-which-is-not-built-in/3645764#3645764). – Nappy Sep 05 '10 at 16:43
  • 3
    String.Join in .NET 4 takes IEnumerable – Ian Mercer Sep 05 '10 at 23:12
-1
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;
}
noopman
  • 660
  • 1
  • 4
  • 15