Skip to content

Commit 601cde5

Browse files
authored
Merge pull request #105 from ColmBhandal/feature/index-map-lambda-init
Feature/index map lambda init
2 parents a938e99 + fae4630 commit 601cde5

File tree

14 files changed

+230
-30
lines changed

14 files changed

+230
-30
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3030
- [BREAKING] Refactored File and Directory Facades & decorators. Updated File creation to throw exception if directory already exists. (#94)
3131
- [BREAKING] Refactored how the GitHub build works to support a release strategy with pre-releases and semantic versioning. No code changes. (#34)
3232
- Added class to enumerate over arithmetic sequences of ints (#99)
33+
- Added new map functions that take indices into account (#103)
34+
- Added support for lambda/constant array initialisation (#104)
3335

3436
### Added
3537
- Support for writing a 1D one-based array to a 2D one-based array (#9)

CsharpExtras/Api/CsharpExtrasApi.cs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,24 +60,37 @@ public IOneBasedArray2D<TVal> NewOneBasedArray2D<TVal>(TVal[,] zeroBasedBackingA
6060
}
6161
public IOneBasedArray2D<TVal> NewOneBasedArray2D<TVal>(int rows, int columns)
6262
{
63-
TVal[,] zeroBased = new TVal[rows, columns];
64-
return NewOneBasedArray2D(zeroBased);
63+
return new OneBasedArray2DImpl<TVal>(rows, columns);
6564
}
65+
public IOneBasedArray2D<TVal> NewOneBasedArray2D<TVal>(int rows, int columns, Func<int, int, TVal> initialiser)
66+
{
67+
IOneBasedArray2D<TVal> array = new OneBasedArray2DImpl<TVal>(rows, columns);
68+
return array.Map((i, j, _) => initialiser(i, j));
69+
}
70+
public IOneBasedArray2D<TVal> NewOneBasedArray2D<TVal>(int rows, int columns, TVal initialValue) =>
71+
NewOneBasedArray2D(rows, columns, (i, j) => initialValue);
6672

6773
public IOneBasedArray<TVal> NewOneBasedArray<TVal>(TVal[] zeroBasedBackingArray)
6874
{
6975
return new OneBasedArrayImpl<TVal>(zeroBasedBackingArray);
7076
}
7177

72-
public ISequentialIntProvider NewSequentialIntProvider(int start, int step)
78+
public IOneBasedArray<TVal> NewOneBasedArray<TVal>(int size)
7379
{
74-
return new SequentialIntProviderImpl(start, step);
80+
return new OneBasedArrayImpl<TVal>(size);
81+
}
82+
public IOneBasedArray<TVal> NewOneBasedArray<TVal>(int size, Func<int, TVal> initialiser)
83+
{
84+
IOneBasedArray<TVal> array = new OneBasedArrayImpl<TVal>(size);
85+
return array.Map((i, x) => initialiser(i));
7586
}
7687

77-
public IOneBasedArray<TVal> NewOneBasedArray<TVal>(int size)
88+
public IOneBasedArray<TVal> NewOneBasedArray<TVal>(int size, TVal initialValue) =>
89+
NewOneBasedArray(size, i => initialValue);
90+
91+
public ISequentialIntProvider NewSequentialIntProvider(int start, int step)
7892
{
79-
TVal[] zeroBased = new TVal[size];
80-
return NewOneBasedArray(zeroBased);
93+
return new SequentialIntProviderImpl(start, step);
8194
}
8295

8396
public IFileDecorator NewFileDecorator() => new FileDecoratorImpl();

CsharpExtras/Api/ICsharpExtrasApi.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,9 @@ public interface ICsharpExtrasApi
4949
ICurryDictionary<TKey, TVal> NewCurryDictionary<TKey, TVal>(int arity);
5050
ICurryDictionary<TKey, TVal> NewCurryDictionary<TKey, TVal>(PositiveInteger arity);
5151
ISequentialIntProvider NewSequentialIntProvider(int start, int step);
52+
IOneBasedArray2D<TVal> NewOneBasedArray2D<TVal>(int rows, int columns, Func<int, int, TVal> initialiser);
53+
IOneBasedArray<TVal> NewOneBasedArray<TVal>(int size, Func<int, TVal> initialiser);
54+
IOneBasedArray2D<TVal> NewOneBasedArray2D<TVal>(int rows, int columns, TVal initialValue);
55+
IOneBasedArray<TVal> NewOneBasedArray<TVal>(int size, TVal initialValue);
5256
}
5357
}

CsharpExtras/Enumerable/OneBased/IOneBasedArray.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ public interface IOneBasedArray<TVal> : IEnumerable<TVal>
2323
IDictionary<TVal, IList<int>> FindDuplicateIndices();
2424
IOneBasedArray<TResult> ZipArray<TOther, TResult>(Func<TVal, TOther, TResult> zipper, IOneBasedArray<TOther> other);
2525
IOneBasedArray<TResult> Map<TResult>(Func<TVal, TResult> mapper);
26+
/// <summary>
27+
/// Maps elements of this array by applying a function on the existing elements plus their one-based indices.
28+
/// </summary>
29+
/// <param name="mapper">A function which takes a value & a one-based index and returns a result</param>
30+
/// <returns>A new array, the same size as this one, filled with the result of applying the mapper function to the original values & one-based indices.</returns>
31+
IOneBasedArray<TResult> Map<TResult>(Func<int, TVal, TResult> mapper);
2632

2733
IDictionary<TVal, IList<int>> InverseMap();
2834

CsharpExtras/Enumerable/OneBased/IOneBasedArray2D.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ public interface IOneBasedArray2D<TVal> : IEnumerable<TVal>
1515

1616
int GetLength(int dimZeroBased);
1717
IOneBasedArray2D<TResult> Map<TResult>(Func<TVal, TResult> mapper);
18+
/// <summary>
19+
/// Maps elements in this array to a new array, using a mapper function that takes one-based row/column indices as arguments
20+
/// </summary>
21+
/// <param name="mapper">Takes as arguments a row index, column index and value in the source array and returns the values for the corresponding row/column in the new array</param>
22+
/// <returns>A new array containing mapped values</returns>
23+
IOneBasedArray2D<TResult> Map<TResult>(Func<int, int, TVal, TResult> mapper);
1824

1925
/// <summary>
2026
/// Zip two 2D arrays into a single 2D array using a custom zipper function.

CsharpExtras/Enumerable/OneBased/OneBasedArray.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ public OneBasedArrayImpl(TVal[] zeroBasedBackingArray)
1717
_backingArray = zeroBasedBackingArray;
1818
}
1919

20+
public OneBasedArrayImpl(int size) : this(new TVal[size])
21+
{
22+
}
23+
2024
public TVal this[int oneBasedIndex]
2125
{
2226
get
@@ -138,6 +142,13 @@ public IOneBasedArray<TResult> Map<TResult>(Func<TVal, TResult> mapper)
138142
return new OneBasedArrayImpl<TResult>(zeroBasedMapped);
139143
}
140144

145+
public IOneBasedArray<TResult> Map<TResult>(Func<int, TVal, TResult> mapper)
146+
{
147+
TResult zeroBasedFunc(int i, TVal x) => mapper(i + 1, x);
148+
TResult[] zeroBasedMapped = ZeroBasedEquivalent.Map(zeroBasedFunc);
149+
return new OneBasedArrayImpl<TResult>(zeroBasedMapped);
150+
}
151+
141152
public IDictionary<TVal, IList<int>> FindDuplicateIndices()
142153
{
143154
IDictionary<TVal, IList<int>> zeroBasedDuplicates = ZeroBasedEquivalent.FindDuplicateIndices();

CsharpExtras/Enumerable/OneBased/OneBasedArray2D.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ public OneBasedArray2DImpl(TVal[,] backingArray)
2626
ZeroBasedEquivalent = backingArray;
2727
}
2828

29+
public OneBasedArray2DImpl(int rows, int columns) : this(new TVal[rows, columns])
30+
{
31+
}
32+
2933
public TVal this[int oneBasedIndex0, int oneBasedIndex1]
3034
{
3135
get
@@ -66,6 +70,13 @@ public IOneBasedArray2D<TResult> Map<TResult>(Func<TVal, TResult> mapper)
6670
return new OneBasedArray2DImpl<TResult>(mapped);
6771
}
6872

73+
public IOneBasedArray2D<TResult> Map<TResult>(Func<int, int, TVal, TResult> mapper)
74+
{
75+
TResult zeroBasedFunc(int i, int j, TVal x) => mapper(i + 1, j + 1, x);
76+
TResult[,] zeroBasedMapped = ZeroBasedEquivalent.Map(zeroBasedFunc);
77+
return new OneBasedArray2DImpl<TResult>(zeroBasedMapped);
78+
}
79+
6980
public IOneBasedArray2D<TResult> ZipArray<TOther, TResult>(Func<TVal, TOther, TResult> zipper, IOneBasedArray2D<TOther> other)
7081
{
7182
TResult[,] zipped = ZeroBasedEquivalent.ZipArray(zipper, other.ZeroBasedEquivalent);

CsharpExtras/Extensions/ArrayExtension.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,13 +194,29 @@ public static TResult[] ZipMulti<TOther, TResult>(this TResult[] array, Func<TRe
194194
return currentZip;
195195
}
196196

197+
/// <summary>
198+
/// Creates a new array, populated by mapping the values of the old array using a mapper function.
199+
/// </summary>
200+
/// <param name="mapper">A function which maps an element in the original array to an element in the new array</param>
201+
/// <returns>A new array, whose values are the result of applying the mapper function to the associated element in the source array.</returns>
197202
public static TResult[] Map<TVal, TResult>(this TVal[] array, Func<TVal, TResult> mapper)
203+
{
204+
TResult func(int i, TVal x) => mapper(x);
205+
return array.Map(func);
206+
}
207+
208+
/// <summary>
209+
/// Creates a new array, populated by mapping the values/indices of the old array using a mapper function.
210+
/// </summary>
211+
/// <param name="mapper">A function which maps an element and its index in the original array to an element in the new array.</param>
212+
/// <returns>A new array, whose values are the result of applying the mapper function to the associated element in the source array & its index.</returns>
213+
public static TResult[] Map<TVal, TResult>(this TVal[] array, Func<int, TVal, TResult> mapper)
198214
{
199215
int length = array.Length;
200216
TResult[] resultArray = new TResult[length];
201217
for (int i = 0; i < length; i++)
202218
{
203-
resultArray[i] = mapper(array[i]);
219+
resultArray[i] = mapper(i, array[i]);
204220
}
205221
return resultArray;
206222
}

CsharpExtras/Extensions/ArrayExtension2D.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,17 @@ public static int Count<TVal>(this TVal[,] array, Func<TVal, bool> checkerFuncti
171171
}
172172

173173
public static TResult[,] Map<TVal, TResult>(this TVal[,] array, Func<TVal, TResult> mapper)
174+
{
175+
TResult func(int i, int j, TVal x) => mapper(x);
176+
return array.Map(func);
177+
}
178+
179+
/// <summary>
180+
/// Creates a new array, populated by mapping the values/indices of the old array using a mapper function.
181+
/// </summary>
182+
/// <param name="mapper">A function which maps an element and its row/column indices in the original array to an element in the new array</param>
183+
/// <returns>A new array, whose values are the result of applying the mapper function to the associated element in the source array & its row/column indices.</returns>
184+
public static TResult[,] Map<TVal, TResult>(this TVal[,] array, Func<int, int, TVal, TResult> mapper)
174185
{
175186
int length0 = array.GetLength(0);
176187
int length1 = array.GetLength(1);
@@ -179,7 +190,7 @@ public static int Count<TVal>(this TVal[,] array, Func<TVal, bool> checkerFuncti
179190
{
180191
for (int j = 0; j < length1; j++)
181192
{
182-
resultArray[i, j] = mapper(array[i, j]);
193+
resultArray[i, j] = mapper(i, j, array[i, j]);
183194
}
184195
}
185196
return resultArray;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using CsharpExtras.Api;
2+
using CsharpExtras.Enumerable.OneBased;
3+
using NUnit.Framework;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Text;
8+
9+
namespace CsharpExtrasTest.Api
10+
{
11+
[TestFixture, Category("Unit")]
12+
public class CSharpExtrasApiTest
13+
{
14+
ICsharpExtrasApi? _csharpExtrasApi;
15+
ICsharpExtrasApi CsharpExtrasApi => _csharpExtrasApi ??= new CsharpExtrasApi();
16+
17+
[Test]
18+
public void GIVEN_IndexPairInitialisationFunction_WHEN_Initialise1DOneBasedArray_THEN_ResultIsAsExpected()
19+
{
20+
//Assemble
21+
22+
Func<int, int, (int, int)> func = (i, j) => (i, j);
23+
24+
//Act
25+
IOneBasedArray2D<(int, int)> result = CsharpExtrasApi.NewOneBasedArray2D(2, 2, func);
26+
27+
//Assert
28+
Assert.AreEqual(new (int, int)[,] { { (1, 1), (1, 2) }, { (2,1), (2, 2) } }, result.ZeroBasedEquivalent);
29+
}
30+
31+
[Test]
32+
public void GIVEN_Constant_WHEN_Initialise2DOneBasedArray_THEN_ResultantOneBasedArrayIsAsExpected()
33+
{
34+
//Assemble
35+
36+
const int C = 7;
37+
38+
//Act
39+
IOneBasedArray2D<int> result = CsharpExtrasApi.NewOneBasedArray2D(2, 2, C);
40+
41+
//Assert
42+
Assert.AreEqual(new int[,] { { C, C }, { C, C } }, result.ZeroBasedEquivalent);
43+
}
44+
45+
[Test]
46+
public void GIVEN_IdentityInitialisationFunction_WHEN_Initialise1DOneBasedArray_THEN_ResultIsAsExpected()
47+
{
48+
//Assemble
49+
50+
Func<int, int> func = i => i;
51+
52+
//Act
53+
IOneBasedArray<int> result = CsharpExtrasApi.NewOneBasedArray(3, func);
54+
55+
//Assert
56+
Assert.AreEqual(new int[] { 1, 2, 3 }, result.ZeroBasedEquivalent);
57+
}
58+
59+
[Test]
60+
public void GIVEN_Constant_WHEN_Initialise1DOneBasedArray_THEN_ResultantOneBasedArrayIsAsExpected()
61+
{
62+
//Assemble
63+
64+
const int C = 7;
65+
66+
//Act
67+
IOneBasedArray<int> result = CsharpExtrasApi.NewOneBasedArray(3, C);
68+
69+
//Assert
70+
Assert.AreEqual(new int[] { C, C, C }, result.ZeroBasedEquivalent);
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)