Skip to content

Instantly share code, notes, and snippets.

@jonasraoni
Created July 14, 2018 14:46
Show Gist options
  • Save jonasraoni/5ac06c17d096e2ac4117ca03a2f9244c to your computer and use it in GitHub Desktop.
Save jonasraoni/5ac06c17d096e2ac4117ca03a2f9244c to your computer and use it in GitHub Desktop.
Flatten Array in C#

Flatten Array

  • Developed using Visual Studio Community and .NET Framework 4.7.1.
  • Compatible with all types of arrays.
  • Generics was used to define the return type.
  • Unit testing done through MSTest.
using System;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// Extends the Array with the Flatten method
/// </summary>
public static class Flattener {
/// <summary>
/// Given a N-dimensional array, flattens it into a new one-dimensional array without modifying the elements' order
/// </summary>
/// <typeparam name="T">The type of elements contained in the array</typeparam>
/// <param name="data">The input array</param>
/// <returns>A flattened array</returns>
public static T[] Flatten<T>(this Array data) {
var list = new List<T>();
var stack = new Stack<IEnumerator>();
stack.Push(data.GetEnumerator());
do {
for (var iterator = stack.Pop(); iterator.MoveNext();) {
if (iterator.Current is Array) {
stack.Push(iterator);
iterator = (iterator.Current as IEnumerable).GetEnumerator();
}
else
list.Add((T)iterator.Current);
}
}
while (stack.Count > 0);
return list.ToArray();
}
}
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace FlattenerTests {
[TestClass]
public class FlattenerTests {
[TestMethod]
[Description("Should return a one-dimensional with the right data type")]
public void Flatten_ReturnsRightDataType() {
Assert.IsInstanceOfType(new int[,,,,] { }.Flatten<int>(), typeof(int[]));
Assert.IsInstanceOfType(new char[][] { }.Flatten<char>(), typeof(char[]));
Assert.IsInstanceOfType(new string[] { }.Flatten<string>(), typeof(string[]));
}
[TestMethod]
[Description("The elements' order should be kept for multidimensional/jagged arrays")]
public void Flatten_MultidimensionalArray_KeepsElementsOrder() {
var intArray = new[, ,] { { { 1, 1 }, { 2, 3 } } };
CollectionAssert.AreEqual(intArray.Flatten<int>(), new[] { 1, 1, 2, 3 });
var dynamicJaggedArray = new dynamic[] { 1, new dynamic[] { "2", 3, new { prop = 123 } } };
CollectionAssert.AreEqual(dynamicJaggedArray.Flatten<dynamic>(), new dynamic[] { 1, "2", 3, new { prop = 123 } });
var intJaggedArray = new int[][] { new int[] { 1, 1 }, new int[] { 2, 3, 4 } };
CollectionAssert.AreEqual(intJaggedArray.Flatten<int>(), new[] { 1, 1, 2, 3, 4 });
var stringJaggedArray = new dynamic[] { new[] { "a" }, new dynamic[] { "b", new[] { "c" } } };
CollectionAssert.AreEqual(stringJaggedArray.Flatten<string>(), new[] { "a", "b", "c" });
}
[TestMethod]
[Description("An empty array should return an empty array")]
public void Flatten_EmptyArray_ReturnsEmptyArray() {
var jaggedIntArray = new int[][][] { };
Assert.AreEqual(jaggedIntArray.Flatten<int>().Length, 0);
var intArray = new int[,,] { };
Assert.AreEqual(intArray.Flatten<int>().Length, 0);
}
[TestMethod]
[Description("Flattening an array of a given type into a different type should fail")]
public void Flatten_IncompatibleType_Fail() {
var dynamicArray = new dynamic[] { 1, "2", 3, new { prop = 123 } };
Assert.ThrowsException<InvalidCastException>(() => dynamicArray.Flatten<string>());
var shortArray = new short[] { 1, 2, 3 };
Assert.ThrowsException<InvalidCastException>(() => shortArray.Flatten<int>());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment