From 7bc0f1dd7ff89428fae7f859bfeafb8d56387704 Mon Sep 17 00:00:00 2001 From: zzandy Date: Thu, 15 Apr 2010 10:25:13 +0300 Subject: [PATCH] Adding C# solution. Collection of usefull extension methods for .NET generic collection. --- C#/ArrayTools.cs | 272 ++++++++++++++++++++++++++++++++++++++++++ C#/DictionaryToArray.cs | 33 +++++ C#/EnumerableCompare.cs | 54 +++++++++ C#/EnumerableFilter.cs | 29 +++++ C#/EnumerableForEach.cs | 25 ++++ C#/EnumerableIn.cs | 13 ++ C#/EnumerableJoin.cs | 13 ++ C#/EnumerableMap.cs | 28 +++++ C#/EnumerableReduce.cs | 94 +++++++++++++++ C#/EnumerableSome.cs | 51 ++++++++ C#/IEnumerableExtras.csproj | 74 ++++++++++++ C#/ListIndexOf.cs | 48 ++++++++ C#/Pair.cs | 46 +++++++ C#/Properties/AssemblyInfo.cs | 36 ++++++ 14 files changed, 816 insertions(+) create mode 100644 C#/ArrayTools.cs create mode 100644 C#/DictionaryToArray.cs create mode 100644 C#/EnumerableCompare.cs create mode 100644 C#/EnumerableFilter.cs create mode 100644 C#/EnumerableForEach.cs create mode 100644 C#/EnumerableIn.cs create mode 100644 C#/EnumerableJoin.cs create mode 100644 C#/EnumerableMap.cs create mode 100644 C#/EnumerableReduce.cs create mode 100644 C#/EnumerableSome.cs create mode 100644 C#/IEnumerableExtras.csproj create mode 100644 C#/ListIndexOf.cs create mode 100644 C#/Pair.cs create mode 100644 C#/Properties/AssemblyInfo.cs diff --git a/C#/ArrayTools.cs b/C#/ArrayTools.cs new file mode 100644 index 0000000..85ae98b --- /dev/null +++ b/C#/ArrayTools.cs @@ -0,0 +1,272 @@ +using System; + +namespace IEnumerableExtras +{ + /// + /// Helper class containing tools to deal with arrays + /// + public static class ArrayTools + { + /// + /// Convert a x based array to a 0 based array. + /// Only works with one or two dimensional arrays. + /// + /// 'x' based array + /// 0 based array + public static Array ConvertTo0Based( Array xBased ) + { + Array zeroBasedArray = null; + + // Do nothing if array is null or empty + if ( xBased != null && xBased.Length > 0 ) + { + // Get number of dimensions + int arrayDimensions = xBased.Rank; + + if ( arrayDimensions == 1 ) + { + // Code for one dimensional array + int ubound1 = xBased.GetUpperBound( 0 ); + int lbound1 = xBased.GetLowerBound( 0 ); + + zeroBasedArray = Array.CreateInstance( xBased.GetValue( 1 ).GetType(), + new[] {ubound1 - lbound1 + 1}, new[] {0} ); + + Array.Copy( xBased, lbound1, zeroBasedArray, 0, xBased.Length ); + } + else if ( arrayDimensions == 2 ) + { + // Code for two dimensional arrays + int ubound1 = xBased.GetUpperBound( 0 ); + int lbound1 = xBased.GetLowerBound( 0 ); + int ubound2 = xBased.GetUpperBound( 1 ); + int lbound2 = xBased.GetLowerBound( 1 ); + + zeroBasedArray = Array.CreateInstance( xBased.GetValue( 1, 1 ).GetType(), + new[] {ubound1 - lbound1 + 1, ubound2 - lbound2 + 1}, + new[] {0, 0} ); + + Array.Copy( xBased, lbound1, zeroBasedArray, 0, xBased.Length ); + } + else + { + throw new ApplicationException( "Cannot rebase arrays of more than 2 dimensions" ); + } + } + + return zeroBasedArray; + } + + + /// + /// Converts a zero based array to a 1 based array + /// Only works with 1 or 2 dimensional arrays. + /// + /// Zero based array + /// 1 based array + public static Array ConvertTo1Based( Array zeroBased ) + { + return ConvertTo1Based( zeroBased, 0, 0 ); + } + + /// + /// Converts a zero based array to a 1 based array + /// Only works with 1 or 2 dimensional arrays. + /// + /// Zero based array + /// How many rows to skip. + /// 1 based array + public static Array ConvertTo1Based( Array zeroBased, int di ) + { + return ConvertTo1Based( zeroBased, di, 0 ); + } + + /// + /// Converts a zero based array to a 1 based array + /// Only works with 1 or 2 dimensional arrays. + /// + /// Zero based array + /// How many rows to skip. + /// How many columns to skip. + /// 1 based array + public static Array ConvertTo1Based( Array zeroBased, int di, int dj ) + { + if ( di < 0 ) + { + throw new ArgumentException( "di must be greater or equal to 0.", "di" ); + } + if ( dj < 0 ) + { + throw new ArgumentException( "dj must be greater or equal to 0.", "dj" ); + } + + Array newArray = null; + + if ( zeroBased != null && zeroBased.Length > 0 ) + { + // Get number of dimensions + int arrayDimensions = zeroBased.Rank; + + if ( arrayDimensions == 1 ) + { + // Code to copy one dimensional arrays + int ubound1 = zeroBased.GetUpperBound( 0 ) - di; + + newArray = Array.CreateInstance( zeroBased.GetType().GetElementType(), new[] {ubound1 + 1}, + new[] {1} ); + + for ( int i = 0; i <= ubound1; ++i ) + { + newArray.SetValue( zeroBased.GetValue( i + di ), i + 1 ); + } + + //Array.Copy( zeroBased, Math.Abs( di ), newArray, 1, zeroBased.Length ); + } + else if ( arrayDimensions == 2 ) + { + // Code to copy two dimensional arrays + int ubound1 = zeroBased.GetUpperBound( 0 ) - di; + int ubound2 = zeroBased.GetUpperBound( 1 ) - dj; + + Type type = GetArrayType( zeroBased ); + + newArray = Array.CreateInstance( type, new[] {ubound1 + 1, ubound2 + 1}, new[] {1, 1} ); + + + for ( int i = 0; i <= ubound1; ++i ) + { + for ( int j = 0; j <= ubound2; ++j ) + { + newArray.SetValue( zeroBased.GetValue( i + di, j + dj ), i + 1, j + 1 ); + } + } + + //Array.Copy(zeroBased, Math.Abs(di + dj), newArray, 1, zeroBased.Length); + } + else + { + throw new ApplicationException( "Cannot rebase arrays of more than 2 dimensions" ); + } + } + + return newArray; + } + + private static Type GetArrayType( Array array ) + { + foreach ( object array1 in array ) + { + if ( array1 != null ) + { + return array1.GetType(); + } + } + + return null; + } + + /// + /// Get onde dimensional array froma two dimensional one. + /// + /// + /// + /// + public static double[] Extract1dFrom2d( double[,] array2D, int index ) + { + int secondDimCount = array2D.GetUpperBound( 1 ) + 1; + + double[] result = new double[secondDimCount]; + + for ( int i = 0; i < secondDimCount; i++ ) + { + result[ i ] = array2D[ index, i ]; + } + return result; + } + + /// + /// Convert an istance of to zero based concrete array. + /// + /// + /// + /// + public static object AsArray< TValue >( Array a ) + { + return AsArray( a, 0, 0 ); + } + + /// + /// Convert an istance of to zero based concrete array. + /// + /// + /// + /// Starting index i + /// + public static object AsArray< TValue >( Array a, int i0 ) + { + return AsArray( a, i0, 0 ); + } + + /// + /// Convert an istance of to zero based concrete array. + /// + /// + /// + /// Starting index i + /// Starting + /// + public static object AsArray< TValue >( Array a, int i0, int j0 ) + { + object res = null; + if ( a != null ) + { + switch ( a.Rank ) + { + case 2: + TValue[,] e = + new TValue[Math.Max( a.GetUpperBound( 0 ), 0 ) + i0,Math.Max( a.GetUpperBound( 1 ), 0 ) + j0 + ]; + for ( int i = a.GetLowerBound( 0 ); i <= a.GetUpperBound( 0 ); ++i ) + { + for ( int j = a.GetLowerBound( 1 ); j <= a.GetUpperBound( 1 ); ++j ) + { + e[ i - a.GetLowerBound( 0 ) + i0, j - a.GetLowerBound( 1 ) + j0 ] = + ( TValue )a.GetValue( i, j ); + } + } + res = e; + break; + case 1: + TValue[] x = new TValue[Math.Max( a.GetUpperBound( 0 ), 0 ) + i0]; + for ( int i = a.GetLowerBound( 0 ); i <= a.GetUpperBound( 0 ); ++i ) + { + x[ i - a.GetLowerBound( 0 ) + i0 ] = ( TValue )a.GetValue( i ); + } + res = x; + break; + default: + break; + } + } + else + { + res = new TValue[0]; + } + + return res; + } + + /// + /// Initializes array elements with . + /// + /// + /// + public static void Initialize( this Array array, object value ) + { + for ( int i = 0; i < array.GetLength( 0 ); i++ ) + { + array.SetValue( value, i ); + } + } + } +} \ No newline at end of file diff --git a/C#/DictionaryToArray.cs b/C#/DictionaryToArray.cs new file mode 100644 index 0000000..f744425 --- /dev/null +++ b/C#/DictionaryToArray.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; + +namespace IEnumerableExtras +{ + /// + /// Provedes extension method for to convert dictionary to an array. + /// + public static class DictionaryToArray + { + /// + /// Convert this instance of to a rectangular + /// arry of type . + /// + /// Type for both keys and values of dictionary. + /// + /// + public static T[,] ToArray< T >( this IDictionary dictionary ) + { + T[,] result = new T[dictionary.Count,2]; + int i = 0; + + foreach ( KeyValuePair pair in dictionary ) + { + result[ i, 0 ] = pair.Key; + result[ i, 1 ] = pair.Value; + + ++i; + } + + return result; + } + } +} \ No newline at end of file diff --git a/C#/EnumerableCompare.cs b/C#/EnumerableCompare.cs new file mode 100644 index 0000000..1df82cc --- /dev/null +++ b/C#/EnumerableCompare.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; + +namespace IEnumerableExtras +{ + /// + /// Compare extension. + /// + public static class EnumerableCompare + { + /// + /// Compare this instance of with another instance + /// if same type using equivalence function and produce a list of items present + /// in both collections and a list of items missing from second collection. + /// + /// + /// + /// + /// + /// + /// + public static IEnumerable> Compare< TValue >( this IEnumerable a, + IEnumerable b, + out IEnumerable missingFromOther, + Func equivFunc ) + { + List> common = new List>(); + List missing = new List(); + + foreach ( TValue fromA in a ) + { + bool found = false; + + foreach ( TValue fromB in b ) + { + if ( equivFunc( fromA, fromB ) ) + { + common.Add( new Pair( fromA, fromB ) ); + found = true; + break; + } + } + + if ( !found ) + { + missing.Add( fromA ); + } + } + + missingFromOther = missing; + return common; + } + } +} \ No newline at end of file diff --git a/C#/EnumerableFilter.cs b/C#/EnumerableFilter.cs new file mode 100644 index 0000000..51382d2 --- /dev/null +++ b/C#/EnumerableFilter.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; + +namespace IEnumerableExtras +{ + /// + /// Provides Filter extension. + /// + public static class EnumerableFilter + { + /// + /// Filter out those items in this collections that don't satisfy . + /// + /// /typeparam> + /// + /// + /// + public static IEnumerable Filter< T >( this IEnumerable collection, Func filterFunc ) + { + foreach ( T item in collection ) + { + if ( filterFunc( item ) ) + { + yield return item; + } + } + } + } +} \ No newline at end of file diff --git a/C#/EnumerableForEach.cs b/C#/EnumerableForEach.cs new file mode 100644 index 0000000..adedb11 --- /dev/null +++ b/C#/EnumerableForEach.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; + +namespace IEnumerableExtras +{ + /// + /// for eah extension. + /// + public static class EnumerableForEach + { + /// + /// Apply function to each element in this instance of . + /// + /// + /// + /// + public static void ForEach< T >( this IEnumerable collection, Action action ) + { + foreach ( var item in collection ) + { + action( item ); + } + } + } +} \ No newline at end of file diff --git a/C#/EnumerableIn.cs b/C#/EnumerableIn.cs new file mode 100644 index 0000000..32c79a0 --- /dev/null +++ b/C#/EnumerableIn.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using System.Linq; + +namespace IEnumerableExtras +{ + public static class EnumerableIn + { + public static bool In< T >( this T needle, IEnumerable heystack ) + { + return heystack.Contains( needle ); + } + } +} \ No newline at end of file diff --git a/C#/EnumerableJoin.cs b/C#/EnumerableJoin.cs new file mode 100644 index 0000000..22b93d9 --- /dev/null +++ b/C#/EnumerableJoin.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using System.Text; + +namespace IEnumerableExtras +{ + public static class EnumerableJoin + { + public static string Join< T >( this IEnumerable enumerable, string glue ) + { + return enumerable.Reduce( new StringBuilder(), ( sb, item ) => sb.Append( item ).Append( glue ) ).ToString(); + } + } +} \ No newline at end of file diff --git a/C#/EnumerableMap.cs b/C#/EnumerableMap.cs new file mode 100644 index 0000000..7d3c0ac --- /dev/null +++ b/C#/EnumerableMap.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; + +namespace IEnumerableExtras +{ + /// + /// map extension. + /// + public static class EnumerableMap + { + /// + /// Produce new instance of by applying + /// predicate to each element in this instance of . + /// + /// This collection's item type. + /// Resulting collection item type. + /// This instance of . + /// Function returnting objects of type based on objects of type . + /// + public static IEnumerable Map< T, TResult >( this IEnumerable collection, Func predicate ) + { + foreach ( var item in collection ) + { + yield return predicate( item ); + } + } + } +} \ No newline at end of file diff --git a/C#/EnumerableReduce.cs b/C#/EnumerableReduce.cs new file mode 100644 index 0000000..74380c6 --- /dev/null +++ b/C#/EnumerableReduce.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace IEnumerableExtras +{ + /// + /// reduce extension. + /// + public static class EnumerableReduce + { + /// + /// Reduce this instance of to a single value of + /// type using given predicate. + /// + /// + /// + /// + /// + public static TValue Reduce(this IEnumerable collection, + Func predicate) + { + bool first = true; + TValue result = default(TValue); + + foreach (TValue value in collection) + { + if (first) + { + result = value; + first = false; + } + else + { + result = predicate(result, value); + } + } + + return result; + } + + /// + /// Reduce this instance of to a single value of + /// type using given predicate. + /// + /// + /// + /// + /// + public static TValue Reduce< TValue >( this IEnumerable collection, + Func predicate ) + { + bool first = true; + TValue result = default( TValue ); + + foreach ( TValue value in collection ) + { + if ( first ) + { + result = value; + first = false; + } + else + { + result = predicate( result, value ); + } + } + + return result; + } + + /// + /// Reduce this instance of to a single value of + /// type using given predicate and an initial value + /// of type . + /// + /// + /// + /// + /// + /// + /// + public static TResult Reduce< TValue, TResult >( this IEnumerable collection, TResult init, + Func predicate ) + { + foreach ( TValue value in collection ) + { + init = predicate( init, value ); + } + + return init; + } + } +} \ No newline at end of file diff --git a/C#/EnumerableSome.cs b/C#/EnumerableSome.cs new file mode 100644 index 0000000..79f614b --- /dev/null +++ b/C#/EnumerableSome.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; + +namespace IEnumerableExtras +{ + /// + /// Provides Some/All extension. + /// + public static class EnumerableSome + { + /// + /// Check if any items in this collection satisfy . + /// + /// + /// + /// + /// + public static bool Some< T >( this IEnumerable collection, Func testFunc ) + { + foreach ( T enumerable in collection ) + { + if ( testFunc( enumerable ) ) + { + return true; + } + } + + return false; + } + + /// + /// Check if all of this collection items satisfy . + /// + /// + /// + /// + /// + public static bool All< T >( this IEnumerable collection, Func testFunc ) + { + foreach ( T enumerable in collection ) + { + if ( !testFunc( enumerable ) ) + { + return false; + } + } + + return true; + } + } +} \ No newline at end of file diff --git a/C#/IEnumerableExtras.csproj b/C#/IEnumerableExtras.csproj new file mode 100644 index 0000000..71b60cd --- /dev/null +++ b/C#/IEnumerableExtras.csproj @@ -0,0 +1,74 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {F5085693-DD41-46BF-A918-916926CE650B} + Library + Properties + IEnumerableExtras + IEnumerableExtras + v3.5 + 512 + SAK + SAK + SAK + SAK + + + true + full + false + ..\..\build\bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\build\bin\Release\ + TRACE + prompt + 4 + + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/C#/ListIndexOf.cs b/C#/ListIndexOf.cs new file mode 100644 index 0000000..f7887ae --- /dev/null +++ b/C#/ListIndexOf.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; + +namespace IEnumerableExtras +{ + public static class ListIndexOf + { + /// + /// Return index of first element of this list satisfying filter function or -1. + /// + /// + /// + /// + /// + public static int IndexOf< T >( this IList list, Func filterFunc ) + { + return IndexOf( list, filterFunc, 1 ); + } + + /// + /// Return index of first element of this list satisfying filter function or -1. + /// + /// + /// + /// Quntifier, index will be divisible by this number + /// + /// + public static int IndexOf< T >( this IList list, Func filterFunc, int quant ) + { + if ( quant <= 0 ) + { + throw new ArgumentException( "Qunatifier must be greater than zero.", "quant" ); + } + + int index = -1; + for ( int i = 0; i < list.Count; i += quant ) + { + if ( filterFunc( list[ i ] ) ) + { + index = i; + break; + } + } + + return index; + } + } +} \ No newline at end of file diff --git a/C#/Pair.cs b/C#/Pair.cs new file mode 100644 index 0000000..e022de1 --- /dev/null +++ b/C#/Pair.cs @@ -0,0 +1,46 @@ +namespace IEnumerableExtras +{ + /// + /// Represents a pair of items of type . + /// + /// + public class Pair< TValue > + { + private readonly TValue _left; + private readonly TValue _right; + + /// + /// Initialize an instance of with two + /// items of type . + /// + /// + /// + public Pair( TValue left, TValue right ) + { + _left = left; + _right = right; + } + + /// + /// Gets first (left) item. + /// + public TValue Left + { + get + { + return _left; + } + } + + /// + /// Gets second (right) item. + /// + public TValue Right + { + get + { + return _right; + } + } + } +} \ No newline at end of file diff --git a/C#/Properties/AssemblyInfo.cs b/C#/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..16da8ad --- /dev/null +++ b/C#/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("IEnumerableExtras")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("EPAM Systems")] +[assembly: AssemblyProduct("IEnumerableExtras")] +[assembly: AssemblyCopyright("Copyright © EPAM Systems 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("d7c44758-7fcb-491d-ae76-d6d2b4fa5f09")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] -- 2.11.4.GIT