Added (array of array).Flatten extension.
[IEnumerableExtras.git] / C# / ArrayTools.cs
blob85ae98b0d12666db5472dbcffa2efef12385a50a
1 using System;
3 namespace IEnumerableExtras
5 /// <summary>
6 /// Helper class containing tools to deal with arrays
7 /// </summary>
8 public static class ArrayTools
10 /// <summary>
11 /// Convert a x based array to a 0 based array.
12 /// Only works with one or two dimensional arrays.
13 /// </summary>
14 /// <param name="xBased">'x' based array</param>
15 /// <returns>0 based array</returns>
16 public static Array ConvertTo0Based( Array xBased )
18 Array zeroBasedArray = null;
20 // Do nothing if array is null or empty
21 if ( xBased != null && xBased.Length > 0 )
23 // Get number of dimensions
24 int arrayDimensions = xBased.Rank;
26 if ( arrayDimensions == 1 )
28 // Code for one dimensional array
29 int ubound1 = xBased.GetUpperBound( 0 );
30 int lbound1 = xBased.GetLowerBound( 0 );
32 zeroBasedArray = Array.CreateInstance( xBased.GetValue( 1 ).GetType(),
33 new[] {ubound1 - lbound1 + 1}, new[] {0} );
35 Array.Copy( xBased, lbound1, zeroBasedArray, 0, xBased.Length );
37 else if ( arrayDimensions == 2 )
39 // Code for two dimensional arrays
40 int ubound1 = xBased.GetUpperBound( 0 );
41 int lbound1 = xBased.GetLowerBound( 0 );
42 int ubound2 = xBased.GetUpperBound( 1 );
43 int lbound2 = xBased.GetLowerBound( 1 );
45 zeroBasedArray = Array.CreateInstance( xBased.GetValue( 1, 1 ).GetType(),
46 new[] {ubound1 - lbound1 + 1, ubound2 - lbound2 + 1},
47 new[] {0, 0} );
49 Array.Copy( xBased, lbound1, zeroBasedArray, 0, xBased.Length );
51 else
53 throw new ApplicationException( "Cannot rebase arrays of more than 2 dimensions" );
57 return zeroBasedArray;
61 /// <summary>
62 /// Converts a zero based array to a 1 based array
63 /// Only works with 1 or 2 dimensional arrays.
64 /// </summary>
65 /// <param name="zeroBased">Zero based array</param>
66 /// <returns>1 based array</returns>
67 public static Array ConvertTo1Based( Array zeroBased )
69 return ConvertTo1Based( zeroBased, 0, 0 );
72 /// <summary>
73 /// Converts a zero based array to a 1 based array
74 /// Only works with 1 or 2 dimensional arrays.
75 /// </summary>
76 /// <param name="zeroBased">Zero based array</param>
77 /// <param name="di">How many rows to skip.</param>
78 /// <returns>1 based array</returns>
79 public static Array ConvertTo1Based( Array zeroBased, int di )
81 return ConvertTo1Based( zeroBased, di, 0 );
84 /// <summary>
85 /// Converts a zero based array to a 1 based array
86 /// Only works with 1 or 2 dimensional arrays.
87 /// </summary>
88 /// <param name="zeroBased">Zero based array</param>
89 /// <param name="di">How many rows to skip.</param>
90 /// <param name="dj">How many columns to skip.</param>
91 /// <returns>1 based array</returns>
92 public static Array ConvertTo1Based( Array zeroBased, int di, int dj )
94 if ( di < 0 )
96 throw new ArgumentException( "di must be greater or equal to 0.", "di" );
98 if ( dj < 0 )
100 throw new ArgumentException( "dj must be greater or equal to 0.", "dj" );
103 Array newArray = null;
105 if ( zeroBased != null && zeroBased.Length > 0 )
107 // Get number of dimensions
108 int arrayDimensions = zeroBased.Rank;
110 if ( arrayDimensions == 1 )
112 // Code to copy one dimensional arrays
113 int ubound1 = zeroBased.GetUpperBound( 0 ) - di;
115 newArray = Array.CreateInstance( zeroBased.GetType().GetElementType(), new[] {ubound1 + 1},
116 new[] {1} );
118 for ( int i = 0; i <= ubound1; ++i )
120 newArray.SetValue( zeroBased.GetValue( i + di ), i + 1 );
123 //Array.Copy( zeroBased, Math.Abs( di ), newArray, 1, zeroBased.Length );
125 else if ( arrayDimensions == 2 )
127 // Code to copy two dimensional arrays
128 int ubound1 = zeroBased.GetUpperBound( 0 ) - di;
129 int ubound2 = zeroBased.GetUpperBound( 1 ) - dj;
131 Type type = GetArrayType( zeroBased );
133 newArray = Array.CreateInstance( type, new[] {ubound1 + 1, ubound2 + 1}, new[] {1, 1} );
136 for ( int i = 0; i <= ubound1; ++i )
138 for ( int j = 0; j <= ubound2; ++j )
140 newArray.SetValue( zeroBased.GetValue( i + di, j + dj ), i + 1, j + 1 );
144 //Array.Copy(zeroBased, Math.Abs(di + dj), newArray, 1, zeroBased.Length);
146 else
148 throw new ApplicationException( "Cannot rebase arrays of more than 2 dimensions" );
152 return newArray;
155 private static Type GetArrayType( Array array )
157 foreach ( object array1 in array )
159 if ( array1 != null )
161 return array1.GetType();
165 return null;
168 /// <summary>
169 /// Get onde dimensional array froma two dimensional one.
170 /// </summary>
171 /// <param name="array2D"></param>
172 /// <param name="index"></param>
173 /// <returns></returns>
174 public static double[] Extract1dFrom2d( double[,] array2D, int index )
176 int secondDimCount = array2D.GetUpperBound( 1 ) + 1;
178 double[] result = new double[secondDimCount];
180 for ( int i = 0; i < secondDimCount; i++ )
182 result[ i ] = array2D[ index, i ];
184 return result;
187 /// <summary>
188 /// Convert an istance of <see cref="Array"/> to zero based concrete array.
189 /// </summary>
190 /// <typeparam name="TValue"></typeparam>
191 /// <param name="a"></param>
192 /// <returns></returns>
193 public static object AsArray< TValue >( Array a )
195 return AsArray<TValue>( a, 0, 0 );
198 /// <summary>
199 /// Convert an istance of <see cref="Array"/> to zero based concrete array.
200 /// </summary>
201 /// <typeparam name="TValue"></typeparam>
202 /// <param name="a"></param>
203 /// <param name="i0">Starting index i</param>
204 /// <returns></returns>
205 public static object AsArray< TValue >( Array a, int i0 )
207 return AsArray<TValue>( a, i0, 0 );
210 /// <summary>
211 /// Convert an istance of <see cref="Array"/> to zero based concrete array.
212 /// </summary>
213 /// <typeparam name="TValue"></typeparam>
214 /// <param name="a"></param>
215 /// <param name="i0">Starting index i</param>
216 /// <param name="j0">Starting</param>
217 /// <returns></returns>
218 public static object AsArray< TValue >( Array a, int i0, int j0 )
220 object res = null;
221 if ( a != null )
223 switch ( a.Rank )
225 case 2:
226 TValue[,] e =
227 new TValue[Math.Max( a.GetUpperBound( 0 ), 0 ) + i0,Math.Max( a.GetUpperBound( 1 ), 0 ) + j0
229 for ( int i = a.GetLowerBound( 0 ); i <= a.GetUpperBound( 0 ); ++i )
231 for ( int j = a.GetLowerBound( 1 ); j <= a.GetUpperBound( 1 ); ++j )
233 e[ i - a.GetLowerBound( 0 ) + i0, j - a.GetLowerBound( 1 ) + j0 ] =
234 ( TValue )a.GetValue( i, j );
237 res = e;
238 break;
239 case 1:
240 TValue[] x = new TValue[Math.Max( a.GetUpperBound( 0 ), 0 ) + i0];
241 for ( int i = a.GetLowerBound( 0 ); i <= a.GetUpperBound( 0 ); ++i )
243 x[ i - a.GetLowerBound( 0 ) + i0 ] = ( TValue )a.GetValue( i );
245 res = x;
246 break;
247 default:
248 break;
251 else
253 res = new TValue[0];
256 return res;
259 /// <summary>
260 /// Initializes array elements with <paramref name="value"/>.
261 /// </summary>
262 /// <param name="array"></param>
263 /// <param name="value"></param>
264 public static void Initialize( this Array array, object value )
266 for ( int i = 0; i < array.GetLength( 0 ); i++ )
268 array.SetValue( value, i );