Signum.Utilities.EnumerableExtensions
Contains many simple and useful methods over
IEnumerable<T> that should have been included in Linq.
I'll try to present them to you in an organized way... somehow. Also, they are really simple so we won't get into the details if necessary:
Basic Methods
public static bool Empty<T>(this IEnumerable<T> collection)
public static IEnumerable<T> NotNull<T>(this IEnumerable<T> source) where T : class
public static IEnumerable<T> NotNull<T>(this IEnumerable<T?> source) where T : struct
public static int IndexOf<T>(this IEnumerable<T> collection, T item)
public static int IndexOf<T>(this IEnumerable<T> collection, Func<T, bool> condition)
public static T Single<T>(this IEnumerable<T> collection, string errorMessage)
public static T SingleOrDefault<T>(this IEnumerable<T> collection, string errorMessage)
public static T First<T>(this IEnumerable<T> collection, string errorMessage)
public static T Single<T>(this IEnumerable<T> collection, string errorZero, string errorMoreThanOne)
SingleOrMany and Only
¶
SingleOrMany: The opposite of SingleOrDefault. Throws an exception if the collection has no elements, and returns null when there are more than one.
Only: Like Single but never throws exception. Returns null whether is empty or contains more than one element.
You typically use this two function when you have to ask the server for the 'default' entity using the new Navigator.FindUnique and, if it returns null, you need to open a SearchWindow to let the user pick one option.
public static T SingleOrMany<T>(this IEnumerable<T> collection)
public static T Only<T>(this IEnumerable<T> collection)
A table comparing .Net methods and the new SF ones.
| Name | Empty | One Element | Many Elements |
|---|
| Single | Throws | Returns | Throws |
| SingleOrDefault | Null | Returns | Throws |
| First | Throws | Returns | Returns first |
| FirstOrDefault | Null | Returns | Returns first |
| SingleOrMany (SF) | Throws | Returns | Null |
| Only (SF) | Null | Returns | Null |
And, PreAnd ¶
Allows you to Add one element at the end (And) or at the start (PreAnd) of a sequence without having to convert it to a List.
public static IEnumerable<T> And<T>(this IEnumerable<T> collection, T newItem)
public static IEnumerable<T> PreAnd<T>(this IEnumerable<T> collection, T newItem)
Example:
new[]{ 2, 3 }.Add(4).PreAnd(1).ForeEach(a => Console.Write(a));
Use it with care! It has good performance if you're planning to add just
ONE element, for more than one it's really expensive because the
asymptotic cost is quedratic when using
recursive iterators.
ForEach (deprecated in
)
The lack of value added, and being the cause of some subtle bugs has make ForEach not worth living. R.I.P.
ToString (Very usefull!)
Allows you to concatenate the string representation of some elements using a separator between each of them, but not at the beginning or the end.
public static string ToString<T>(this IEnumerable<T> collection, string separator)
public static string ToString<T>(this IEnumerable<T> collection, Func<T, string> toString, string separator)
Example:
string str = new[] { 1, 2, 3, 4, 5 }.ToString(", ");
You can also use the second overload that takes a lambda to specify how to do the ToString of each element:
string[] sortNames = CultureInfo.InvariantCulture.DateTimeFormat.ShortestDayNames;
string str = new[] { 1, 2, 3, 4, 5 }.ToString(n => ((DayOfWeek)n).ToString(), ", ");
Internally, this function uses
StringBuilder, so it has good performance even with lot of elements, but using this function is
way sorter and much more
composable than using StringBuilder directly.
How Many times you have seen code like this?
StrinbBuilder sb = new StringBuilder();
foreach(int n in new[] { 1, 2, 3, 4, 5 })
{
if(sb.Length > 0)
sb.Write(", ");
sb.Write(n);
}
return sb.ToString();
As you see StringBuilder gets performance by making you
code more!, and forcing you to a very imperative style, and since StringBuilder is mainly used in
for loops concatenation then, well... if I were StringBuilder I would better get another job.
Comma, CommaAnd, CommaOr
¶
Quite similar to ToString extensions method, but if there are more than one element, between the last two writes ' and ' (CommaAnd), ' or ' (CommaOr) or a custom lastSeparator (Comma)
public static string CommaAnd<T>(this IEnumerable<T> collection)
public static string CommaAnd<T>(this IEnumerable<T> collection, Func<T, string> toString)
public static string CommaOr<T>(this IEnumerable<T> collection)
public static string CommaOr<T>(this IEnumerable<T> collection, Func<T, string> toString)
public static string Comma<T>(this IEnumerable<T> collection, string lastSeparator)
public static string Comma<T>(this IEnumerable<T> collection, Func<T, string> toString, string lastSeparator)
Example:
new[]{ 1, 2, 3 }.CommaAnd();
new[]{ 1, 2, 3 }.Comma(n=>n.ToString("00"), " & ");
ToConsole, ToFile
public static void ToConsole<T>(this IEnumerable<T> collection)
public static void ToConsole<T>(this IEnumerable<T> collection, Func<T, string> toString)
public static void ToFile(this IEnumerable<string> collection, string fileName)
public static void ToFile<T>(this IEnumerable<T> collection, Func<T, string> toString, string fileName)
ToDataTable
public static DataTable ToDataTable<T>(this IEnumerable<T> collection)
ToStringTable, FormatTable and ToConsoleTable ¶
public static string[,] ToStringTable<T>(this IEnumerable<T> collection)
public static string FormatTable(this string[,] table)
public static string FormatTable(this string[,] table, bool longHeaders)
public static void WriteFormatedStringTable<T>(this IEnumerable<T> collection, TextWriter textWriter, string title)
public static void ToConsoleTable<T>(this IEnumerable<T> collection, string title)
All these methods make reusable pieces and create behavior by composition, but the most useful method from the client side is ToConsoleTable. Let's see an example:
new DirectoryInfo(@"C:\Users\Public\Pictures\Sample Pictures").GetFiles()
.Select(a=>new
{
a.Name,
Size = a.Length.ToComputerSize(),
a.LastWriteTime,
a.CreationTime
})
.ToConsoleTable("..::My Images::..");
..::My Images::..
Name Size LastWriteTime CreationTime
Butterfly.jpg 303,06 KBytes 13/12/2008 0:28:36 13/12/2008 0:28:40
desktop.ini 1,06 KBytes 13/12/2008 0:51:05 13/12/2008 0:28:40
Field.jpg 297,31 KBytes 13/12/2008 0:28:36 13/12/2008 0:28:40
Flower.jpg 298,06 KBytes 13/12/2008 0:28:36 13/12/2008 0:28:40
Leaves.jpg 299,62 KBytes 13/12/2008 0:28:36 13/12/2008 0:28:40
Rocks.jpg 304,26 KBytes 13/12/2008 0:28:36 13/12/2008 0:28:40
Thumbs.db 115,50 KBytes 29/01/2009 17:17:12 18/01/2009 5:10:16
Tulip.jpg 274,95 KBytes 13/12/2008 0:28:36 13/12/2008 0:28:40
Waterfall.jpg 306,83 KBytes 13/12/2008 0:28:36 13/12/2008 0:28:40
Window.jpg 264,67 KBytes 13/12/2008 0:28:36 13/12/2008 0:28:40
ToWikiTable
ToWikiTable uses ToStringTable to create a table compatible with
Wikipedia and
ScrewTurn Wiki table format:
public static string ToWikiTable<T>(this IEnumerable<T> collection)
WithMin WithMax WithMinMaxPair
Linq already provides a way of retrieving the Min or the Max values in a collection, but it doesn't provide any help if finding the element that has the Min (or Max) something.
public static T WithMin<T, V>(this IEnumerable<T> collection, Func<T, V> valueSelector) where V : IComparable<V>
public static T WithMax<T, V>(this IEnumerable<T> collection, Func<T, V> valueSelector) where V : IComparable<V>
public static MinMax<T> WithMinMaxPair<T, V>(this IEnumerable<T> collection, Func<T, V> valueSelector) where V : IComparable<V>
WithMinMaxPair returns a
MinMax structure.
Example:
var oldestFile = new DirectoryInfo(@"C:\Users\Public\Pictures\Sample Pictures").GetFiles().WithMin(a=>a.CreationTime);
MinMaxPair 
public static Interval<T> MinMaxPair<T>(this IEnumerable<T> collection) where T : struct, IComparable<T>, IEquatable<T>
public static Interval<V> MinMaxPair<T, V>(this IEnumerable<T> collection, Func<T, V> valueSelector) V:struct, IComparable<V>, IEquatable<V>
Because the resulting values are guaranteed to be ordered, they are returned in a Interval structure, not a MinMax.
Example:
new []{ 2, 10, 100, -4, -120}.MinMaxPair();
BiSelect
Very often you need to make transformation on a List that need pair of elements instead of just one element, then Select doesn't fit our needs and we have to use BiSelect.
public static IEnumerable<S> BiSelect<T, S>(this IEnumerable<T> collection, Func<T, T, S> func)
Let's see an example. You have a list of 5 numbers and you want the list of differences from one number to the next one:
new[] { 2, 3, 5, 7, 11}.BiSelect((a, b) => b - a).ToString(", ");
As you see, the resulting list has only 4 because the first element (2) and the last one (29) appear just once. There is another overload that allows you to turn pick between many options:
public static IEnumerable<S> BiSelect<T, S>(this IEnumerable<T> collection, Func<T, T, S> func, BiSelectOptions options)
public enum BiSelectOptions
{
None,
Initial,
Final,
InitialAndFinal,
Circular,
}
Let's test all the options at once in a very cool way:
var nums = new[] { 2, 3, 5, 7, 11};
EnumExtensions.GetValues<BiSelectOptions>()
.Select(opt => new
{
Option = opt,
Result = nums.BiSelect((a, b) => b - a, opt).ToString(", ")
}).ToConsoleTable("-= Test =-");
SelectAggregate
Aggregate function provided by Linq allows to collapse all the elements in a collection using a function, returning a single element as a result.
Often, however, you are interested in all the intermediate values. In this situations SelectAggregate comes to the rescue!
public static IEnumerable<S> SelectAggregate<T, S>(this IEnumerable<T> collection, S seed, Func<S, T, S> aggregate)
Let's see an example. Given a list of 5 ones, the intermediate values of summing all of them:
new[] { 1, 1, 1, 1, 1 }.SelectAggregate(0, (a, b) => a + b).ToString(", ");
As you see, the result has 6 values because the first value (seed) is also returned.
As a curiosity, if you apply this function to the result of the previous example (BiSelect) using the first value as the seed you restore the values:
new[] { 2, 3, 5, 7, 11}.BiSelect((a, b) => b - a).SelectAggregate(2, (a, b) => a + b).ToString(", ");
GroupWhen
Given a flat collection of items, GroupsWhen creates a new group every time isGroupKey evaluates to true, filling the group with all the following elements.
All the initial elements are ignored until the first isGroupKey is found.
public static List<List<T>> SplitList<T>(this IEnumerable<T> collection, Func<T, bool> isSplitter)
Example, let's suppose we have a text file named "countries.txt" like this:
Countries by region:
#Asia
China
Japan
India
#Europe
Germany
France
Spain
#North America
USA
Canada
Mexico
Then we can associate each continent with the following countries like this:
File.ReadAllLines("countries.txt")
.GroupWhen(s => s.StartsWith("#"))
.Select(g => new
{
Region = g.Key.Substring(1),
Countries = g.ToString(", ")
}).ToConsoleTable("-=Results=-");
Printing in the Console:
-=Results=-
Region Countries
Asia China, Japan, India
Europe Germany, France, Spain
North America USA, Canada, Mexico
GroupsOf
GroupsOf creates fixed-size groups of a flatted collection:
public static IEnumerable<List<T>> GroupsOf<T>(this IEnumerable<T> collection, int groupSize)
Example:
new[] { 1, 2, 3, 4, 5, 6, 7 }
.GroupsOf(3);
.ToString(list => list.ToString(","), " || ");
Slice
Slice allows you to get an range of a IEnumerable given the
from and
to indexes of the interval.
The definition is really simple:
public static IEnumerable<T> Slice<T>(this IEnumerable<T> collection, int firstIncluded, int toNotIncluded)
{
return collection.Skip(firstIncluded).Take(toNotIncluded - firstIncluded);
}
Example:
new[] { "a", "b", "c", "d" }.Slice(1, 3).ToString("");
Order
Just a parameterless overload of OrderBy that works on IQuerable<T> where T is itself an IComparable<T>.
There are two overloads, one for IEnumerable and other for IQueryable:
public static IOrderedEnumerable<T> Order<T>(this IEnumerable<T> collection) where T : IComparable<T>
public static IOrderedQueryable<T> Order<T>(this IQueryable<T> collection) where T : IComparable<T>
Example:
new[] { 3,5,1,2 }.Order().ToString("");
Zip
Zip operator is common in functional languages like
Haskell and a possible
new operator of Linq when C# 4.0 live.
In the meantime, Signum Utilities has 6 overloads of Zip operator that are handy in many situations.
Zip operator just mixes two sequences of elements taking an element of each sequence in pairs.
public static IEnumerable<Tuple<A, B>> Zip<A, B>(this IEnumerable<A> colA, IEnumerable<B> colB)
public static IEnumerable<R> Zip<A, B, R>(this IEnumerable<A> colA, IEnumerable<B> colB, Func<A, B, R> mixer)
public static void ZipForeach<A, B>(this IEnumerable<A> colA, IEnumerable<B> colB, Action<A, B> actions)
public static IEnumerable<Tuple<A, B>> ZipStrict<A, B>(this IEnumerable<A> colA, IEnumerable<B> colB)
public static IEnumerable<R> ZipStrict<A, B, R>(this IEnumerable<A> colA, IEnumerable<B> colB, Func<A, B, R> mixer)
public static void ZipForeachStrict<A, B>(this IEnumerable<A> colA, IEnumerable<B> colB, Action<A, B> actions)
Example:
string[] names = { "a", "b", "c", "d" };
int[] ages = { 1, 2, 3, 4, 5, 6 };
names.Zip(ages).ToString(" ");
names.Zip(ages, (letter, number) => letter + number).ToString(" ");
names.ZipForeach(ages, (letter, number) => Console.Write(letter + number));
names.ZipString(ages).ToString(" ");
names.ZipString(ages, (letter, number) => letter + number).ToString(" ");
names.ZipForeachString(ages, (letter, number) => Console.Write(letter + number));
JoinStrict 
Similar to join but whenever there's a mismatch between the two collections throws a nice exception message. The keys shouldn't be repeated in any of the two collections.
public static IEnumerable<R> JoinStrict<K, O, N, R>(
IEnumerable<O> oldCollection,
IEnumerable<N> newCollection,
Func<O, K> oldKeySelector,
Func<N, K> newKeySelector,
Func<O, N, R> resultSelector,
string action )
Example:
new []{1,2,3,4,5}.JoinStrict(new[]{1,3,5,7,9}, a=>a, b=>b, (a,b)=>a, "Joining Numbers");
Usefully to build a 1-to-1 correspondence between elements of two collections, asserting it in the process.
Conversions
Just some extension methods to convert IEnumerbles to collection types already available in .Net 3.5:
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source)
public static ReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> collection)
AsThreadSafe returns a
ThreadSafeEnumerator for the current IEnumerable so you can consume it from different threads at the same time safely.
public static IEnumerable<T> AsThreadSafe<T>(this IEnumerable<T> source)
ToProgressEnumerator creates a
ProgressEnumerator keeps tracks of progress as the IEnumerable gets consumed.
public static IEnumerable<T> ToProgressEnumerator<T>(this IEnumerable<T> source, out IProgressInfo pi)
AddRange / PushRange / EnqueueRange
Finally, just some extension methods over HashSet, Stack, and Queue to make them easier to be used with LINQ Queries.
public static void PushRange<T>(this Stack<T> stack, IEnumerable<T> elements)
public static void EnqueueRange<T>(this Queue<T> queue, IEnumerable<T> elements)
public static void AddRange<T>(this HashSet<T> hashset, IEnumerable<T> coleccion)