From 109f279564a00b2502a4cd04beef659ff2b198e4 Mon Sep 17 00:00:00 2001 From: Tim Maes Date: Sat, 16 Dec 2023 21:20:51 +0100 Subject: [PATCH] Add methods for multi dimensional arrays --- README.md | 19 ++ .../MultiDimensionalArrayTests.cs | 116 +++++++++++ src/ArrayExtensions/ArrayExtensions.csproj | 2 +- .../MultiDimensionalArrayExtensions.cs | 185 ++++++++++++++++++ 4 files changed, 321 insertions(+), 1 deletion(-) create mode 100644 src/ArrayExtensions.Tests/MultiDimensionalArrayTests.cs create mode 100644 src/ArrayExtensions/MultiDimensionalArrayExtensions.cs diff --git a/README.md b/README.md index f30bc43..56aa577 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,25 @@ Or just copy whatever you need from this repository :) |`ToFrequencyMap`| Creates a frequency map (count of each element).| |`Variance`| Calculates the variance of the array elements.| +## Multi Dimensional Array methods + +## Generic Multi Dimensional Array methods + +| Name | Description | +|-------------------------------------|----------------------------------------------------------------------| +| `AllEqual()` | Checks if all elements in a multi-dimensional array are identical. | +| `Contains()` | Checks if the multi-dimensional array contains a specific element. | +| `CountOf()` | Counts occurrences of a specific item in the multi-dimensional array.| +| `DeepCopy()` | Creates a deep copy of the multi-dimensional array. | +| `Fill()` | Fills the multi-dimensional array with a specific value. | +| `FindFirst()` | Finds the first occurrence of an element that matches a condition. | +| `Flatten()` | Flattens a multi-dimensional array into a single-dimensional array. | +| `ForEach()` | Iterates over each element in a multi-dimensional array and executes the provided action. | +| `GetColumn()` | Retrieves a specific column from a multi-dimensional array. | +| `GetRow()` | Retrieves a specific row from a multi-dimensional array. | +| `Rotate90DegreesClockwise()` | Rotates the array 90 degrees clockwise. | +| `Transpose()` | Transposes a two-dimensional array. | + ## License [MIT](https://opensource.org/licenses/MIT) diff --git a/src/ArrayExtensions.Tests/MultiDimensionalArrayTests.cs b/src/ArrayExtensions.Tests/MultiDimensionalArrayTests.cs new file mode 100644 index 0000000..58d11e1 --- /dev/null +++ b/src/ArrayExtensions.Tests/MultiDimensionalArrayTests.cs @@ -0,0 +1,116 @@ +using FluentAssertions; +using Xunit; + +namespace ArrayExtensions.Tests; + +public class MultiDimensionalArrayTests +{ + [Fact] + public void ForEach_ShouldExecuteActionForEachElement() + { + var array = new[,] { { 1, 2 }, { 3, 4 } }; + int sum = 0; + array.ForEach(x => sum += x); + sum.Should().Be(10); + } + + [Fact] + public void Transpose_ShouldTransposeArray() + { + var array = new[,] { { 1, 2 }, { 3, 4 } }; + var transposed = array.Transpose(); + var expected = new[,] { { 1, 3 }, { 2, 4 } }; + transposed.Should().BeEquivalentTo(expected); + } + + [Fact] + public void Flatten_ShouldConvertToSingleDimensionalArray() + { + var array = new[,] { { 1, 2 }, { 3, 4 } }; + var flattened = array.Flatten(); + var expected = new[] { 1, 2, 3, 4 }; + flattened.Should().Equal(expected); + } + + [Fact] + public void DeepCopy_ShouldCreateSeparateArray() + { + var array = new[,] { { "a", "b" }, { "c", "d" } }; + var copy = array.DeepCopy(); + copy.Should().NotBeSameAs(array); + copy.Should().BeEquivalentTo(array); + } + + [Fact] + public void AllEqual_WithIdenticalElements_ShouldReturnTrue() + { + var array = new[,] { { 1, 1 }, { 1, 1 } }; + var result = array.AllEqual(); + result.Should().BeTrue(); + } + + [Fact] + public void CountOf_SpecificValue_ShouldReturnCount() + { + var array = new[,] { { 1, 2 }, { 1, 2 } }; + var count = array.CountOf(1); + count.Should().Be(2); + } + + [Fact] + public void Fill_ShouldFillArrayWithSpecifiedValue() + { + var array = new int[2, 2]; + array.Fill(5); + array.Cast().Should().AllBeEquivalentTo(5); + } + + [Fact] + public void FindFirst_MatchingPredicate_ShouldReturnCoordinates() + { + var array = new[,] { { 1, 2 }, { 3, 4 } }; + var result = array.FindFirst(x => x == 3); + result.Should().Be((1, 0)); + } + + [Fact] + public void FindFirst_NonMatchingPredicate_ShouldReturnNull() + { + var array = new[,] { { 1, 2 }, { 3, 4 } }; + var result = array.FindFirst(x => x == 5); + result.Should().BeNull(); + } + + [Fact] + public void GetRow_ShouldReturnSpecificRow() + { + var array = new[,] { { 1, 2 }, { 3, 4 } }; + var row = array.GetRow(1); + row.Should().Equal(3, 4); + } + + [Fact] + public void GetColumn_ShouldReturnSpecificColumn() + { + var array = new[,] { { 1, 2 }, { 3, 4 } }; + var column = array.GetColumn(1); + column.Should().Equal(2, 4); + } + + [Fact] + public void Rotate90DegreesClockwise_ShouldRotateArray() + { + var array = new[,] { { 1, 2 }, { 3, 4 } }; + var rotated = array.Rotate90DegreesClockwise(); + var expected = new[,] { { 3, 1 }, { 4, 2 } }; + rotated.Should().BeEquivalentTo(expected); + } + + [Fact] + public void Contains_ExistingElement_ShouldReturnTrue() + { + var array = new[,] { { 1, 2 }, { 3, 4 } }; + var result = array.Contains(3); + result.Should().BeTrue(); + } +} \ No newline at end of file diff --git a/src/ArrayExtensions/ArrayExtensions.csproj b/src/ArrayExtensions/ArrayExtensions.csproj index f4d1302..8c1daad 100644 --- a/src/ArrayExtensions/ArrayExtensions.csproj +++ b/src/ArrayExtensions/ArrayExtensions.csproj @@ -10,7 +10,7 @@ https://www.github.com/Tim-Maes/ArrayExtensions https://www.github.com/Tim-Maes/ArrayExtensions array, extensions - 1.2.7 + 1.3.0 true LICENSE.txt README.md diff --git a/src/ArrayExtensions/MultiDimensionalArrayExtensions.cs b/src/ArrayExtensions/MultiDimensionalArrayExtensions.cs new file mode 100644 index 0000000..af4f309 --- /dev/null +++ b/src/ArrayExtensions/MultiDimensionalArrayExtensions.cs @@ -0,0 +1,185 @@ +namespace ArrayExtensions; + +public static class MultiDimensionalArrayExtensions +{ /// + /// Iterates over each element in a multi-dimensional array and executes the provided action. + /// + public static void ForEach(this T[,] array, Action action) + { + for (int i = 0; i < array.GetLength(0); i++) + { + for (int j = 0; j < array.GetLength(1); j++) + { + action(array[i, j]); + } + } + } + + /// + /// Transposes a two-dimensional array. + /// + public static T[,] Transpose(this T[,] array) + { + var rows = array.GetLength(0); + var columns = array.GetLength(1); + var result = new T[columns, rows]; + + for (int i = 0; i < rows; i++) + { + for (int j = 0; j < columns; j++) + { + result[j, i] = array[i, j]; + } + } + + return result; + } + + /// + /// Flattens a multi-dimensional array into a single-dimensional array. + /// + public static T[] Flatten(this T[,] array) + { + var rows = array.GetLength(0); + var columns = array.GetLength(1); + var result = new T[rows * columns]; + int index = 0; + + for (int i = 0; i < rows; i++) + { + for (int j = 0; j < columns; j++) + { + result[index++] = array[i, j]; + } + } + + return result; + } + + /// + /// Creates a deep copy of the multi-dimensional array. + /// Note: Elements in the array must implement the ICloneable interface. + /// + public static T[,] DeepCopy(this T[,] array) where T : ICloneable + { + var rows = array.GetLength(0); + var columns = array.GetLength(1); + var result = new T[rows, columns]; + + for (int i = 0; i < rows; i++) + { + for (int j = 0; j < columns; j++) + { + result[i, j] = (T)array[i, j].Clone(); + } + } + + return result; + } + + /// + /// Checks if all elements in the multi-dimensional array are equal. + /// + public static bool AllEqual(this T[,] array) + { + var first = array[0, 0]; + return array.Cast().All(element => EqualityComparer.Default.Equals(element, first)); + } + + /// + /// Counts occurrences of a specific item in the multi-dimensional array. + /// + public static int CountOf(this T[,] array, T item) where T : IEquatable + { + return array.Cast().Count(x => x.Equals(item)); + } + + /// + /// Fills the multi-dimensional array with a specific value. + /// + public static void Fill(this T[,] array, T value) + { + for (int i = 0; i < array.GetLength(0); i++) + { + for (int j = 0; j < array.GetLength(1); j++) + { + array[i, j] = value; + } + } + } + + /// + /// Finds the first occurrence of an element that matches a condition. + /// + public static (int, int)? FindFirst(this T[,] array, Predicate match) + { + for (int i = 0; i < array.GetLength(0); i++) + { + for (int j = 0; j < array.GetLength(1); j++) + { + if (match(array[i, j])) + { + return (i, j); + } + } + } + + return null; + } + + /// + /// Retrieves a specific row from a multi-dimensional array. + /// + public static T[] GetRow(this T[,] array, int row) + { + var rowLength = array.GetLength(1); + var result = new T[rowLength]; + for (int i = 0; i < rowLength; i++) + { + result[i] = array[row, i]; + } + return result; + } + + /// + /// Retrieves a specific column from a multi-dimensional array. + /// + public static T[] GetColumn(this T[,] array, int column) + { + var columnLength = array.GetLength(0); + var result = new T[columnLength]; + for (int i = 0; i < columnLength; i++) + { + result[i] = array[i, column]; + } + return result; + } + + /// + /// Rotates the array 90 degrees clockwise. + /// + public static T[,] Rotate90DegreesClockwise(this T[,] array) + { + var rows = array.GetLength(0); + var columns = array.GetLength(1); + var result = new T[columns, rows]; + + for (int i = 0; i < rows; i++) + { + for (int j = 0; j < columns; j++) + { + result[j, rows - 1 - i] = array[i, j]; + } + } + + return result; + } + + /// + /// Checks if the multi-dimensional array contains a specific element. + /// + public static bool Contains(this T[,] array, T item) where T : IEquatable + { + return array.Cast().Any(x => x.Equals(item)); + } +}