Signum Framework Logo
"Open framework that encourages convention over configuration, using C# code,
not XML files, to model at the right level of abstraction and achieve deadlines.
...but also has a full Linq provider, and syncs the schema for you!"
Login
RSS

Search

»



Main
Index
Map
Videos
Download
Source code
Tutorials
Forum
FAQ



Image



PoweredBy


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

//Returns true if the collection is empty
public static bool Empty<T>(this IEnumerable<T> collection)

//Removes all null elements in the sequence: Where(a => a != null) 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

//As in List<T> but for any IEnumerable public static int IndexOf<T>(this IEnumerable<T> collection, T item)

//Same but using a condition, not an element public static int IndexOf<T>(this IEnumerable<T> collection, Func<T, bool> condition)

//Uses your own errorMessage when a InvalidOperationException is thrown. 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)

//Different custom errorMessages for zero and more than one elements. NEW in SF 2.0 public static T Single<T>(this IEnumerable<T> collection, string errorZero, string errorMoreThanOne)

SingleOrMany and Only Image

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.

NameEmptyOne ElementMany Elements
SingleThrowsReturnsThrows
SingleOrDefaultNullReturnsThrows
FirstThrowsReturnsReturns first
FirstOrDefaultNullReturnsReturns first
SingleOrMany (SF)ThrowsReturnsNull
Only (SF)NullReturnsNull

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)); 
//Result: 1234

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 Image)

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(", ");

//Result: 1, 2, 3, 4, 5

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(), ", ");

//Result: Monday, Tuesday, Wednesday, Thursday, Friday

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 Image

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(); //Returns: "1, 2 and 3" ("1, 2 y 3" if CurrentCulture is Spanish)
new[]{ 1, 2, 3 }.Comma(n=>n.ToString("00"), " & "); //Returns: "01, 02 & 03"

ToConsole, ToFile

//Write each element in collection in a line in the console: 
public static void ToConsole<T>(this IEnumerable<T> collection)
public static void ToConsole<T>(this IEnumerable<T> collection, Func<T, string> toString)

//Write each element in collection in a line in a text file: 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

//Creates a DataTable with a column for each public property or field on T. Cool for debugging.
public static DataTable ToDataTable<T>(this IEnumerable<T> collection)

ToStringTable, FormatTable and ToConsoleTable

//Creates a bidimensional string array with every public member (property or field) in T.
//Member names are placed in the first row (headers), and values for each element are placed in the following rows. 
public static string[,] ToStringTable<T>(this IEnumerable<T> collection)

//Format a bidimensional string array in a big string //Making room between columns so the longer value (or header if enabled) fits in each column. public static string FormatTable(this string[,] table) public static string FormatTable(this string[,] table, bool longHeaders)

//Uses ToStringTable and FormatTable to write in a TextWriter a formatted table decorated with a title public static void WriteFormatedStringTable<T>(this IEnumerable<T> collection, TextWriter textWriter, string title)

//Uses WriteFormatedStringTable using Console.Out as the textWriter. 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::.."); 

//Returning ..::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.

//Returns the element on collection with the minimum selected value
public static T WithMin<T, V>(this IEnumerable<T> collection, Func<T, V> valueSelector) where V : IComparable<V>

//Returns the element on collection with the maximum selected value public static T WithMax<T, V>(this IEnumerable<T> collection, Func<T, V> valueSelector) where V : IComparable<V>

//Returns a MinMax structure with the elements on collection with the minimum an maximum selected value 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 Image

//Gets the Min and the Max values in the collection iterating over the collection just once. 
public static Interval<T> MinMaxPair<T>(this IEnumerable<T> collection) where T : struct, IComparable<T>, IEquatable<T>

//Gets the Min and the Max values selected by valueSelector in the collection iterating over the collection just once. 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(); //Return Interval<int>(-120, 100)

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(", "); 

//Result: 1, 2, 2, 4

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, // N-1 values (first and last only once) Initial, // N values ( [default(T),first] is computed too) Final, // N values ( [last,default(T)] is computed too ) InitialAndFinal, // N+1 values ([default(T),first] and [last,default(T)] are computed too) Circular, // N values ([last,first] are computed too) }

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 =-");

//-= Test =- //Option Result //None ___1, 2, 2, 4 //Initial 2, 1, 2, 2, 4 //Final ___1, 2, 2, 4, -11 //InitialAndFinal 2, 1, 2, 2, 4, -11 //Circular ___1, 2, 2, 4, -9

//Note: __Underscores__ Added by me to make it easy to understand

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(", ");

//Result: 0, 1, 2, 3, 4, 5

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(", ");
//Result: 2, 3, 5, 7, 11

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(","), " || ");

//Result: 1,2,3 || 4,5,6 || 7

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("");

//Result: "bc"

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("");

//Result: 1235

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.

//Zips two sequences using Tuples, finish on the shorter
public static IEnumerable<Tuple<A, B>> Zip<A, B>(this IEnumerable<A> colA, IEnumerable<B> colB)

//Zips two sequences using a mixer function, finish on the shorter public static IEnumerable<R> Zip<A, B, R>(this IEnumerable<A> colA, IEnumerable<B> colB, Func<A, B, R> mixer)

//Zips two sequences taking an action for each pair and returning void, finish on the shorter public static void ZipForeach<A, B>(this IEnumerable<A> colA, IEnumerable<B> colB, Action<A, B> actions)



//Zips two sequences using Tuples, if not the same length throws InvalidOperationException public static IEnumerable<Tuple<A, B>> ZipStrict<A, B>(this IEnumerable<A> colA, IEnumerable<B> colB)

//Zips two sequences using a mixer function, if not the same length throws InvalidOperationException public static IEnumerable<R> ZipStrict<A, B, R>(this IEnumerable<A> colA, IEnumerable<B> colB, Func<A, B, R> mixer)

//Zips two sequences taking an action for each pair and returning void, if not the same length throws InvalidOperationException public static void ZipForeachStrict<A, B>(this IEnumerable<A> colA, IEnumerable<B> colB, Action<A, B> actions)

Example:

//Given the following arrays:
string[] names = { "a", "b", "c", "d" };
int[] ages = { 1, 2, 3, 4, 5, 6 };

names.Zip(ages).ToString(" "); //Result: [a,1] [b,2] [c,3] [d,4] //([x,y] is the ToString for a Tuple)

names.Zip(ages, (letter, number) => letter + number).ToString(" "); //Result: a1 b2 c3 d4

names.ZipForeach(ages, (letter, number) => Console.Write(letter + number)); //Writes: a1b2c3d4

names.ZipString(ages).ToString(" "); //throws InvalidOperationException("The first collection is shorter");

names.ZipString(ages, (letter, number) => letter + number).ToString(" "); //throws InvalidOperationException("The first collection is shorter");

names.ZipForeachString(ages, (letter, number) => Console.Write(letter + number)); //throws InvalidOperationException("The first collection is shorter");

JoinStrict Image

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");
// Throws an InvalidOperationException with the message: 
// Error Joining Numbers: 
// Laking: 7, 9
// Extra: 2, 4

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:

//Creates a new HashSet with the elements (repeated elements disappear) 
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source)

//Converts the IEnumerable to a ReadOnlyCollection (it necessary) 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)
Creative Commons License Signum Framework Site by Signum Software is licensed under a Creative Commons Attribution 3.0 License.
Powered by ScrewTurn Wiki version 3.0.5.600.