You could have used directly a jagged array, like:
string[][] arrayJagged = new[]
{
new[] { "a", "b", "c" },
new[] { "a", "b", "c" },
new[] { "d", "e", "f" },
new[] { "g", "h", "i" },
};
but you want to dig in the ruins of the past and use multidimensional array, just to make everything more complex.
string[,] stringArray2D = new string[,]
{
{ "a", "b", "c" },
{ "a", "b", "c" },
{ "d", "e", "f" },
{ "g", "h", "i" },
};
Then we will have to convert the multidimensional array to a jagged array:
string[][] arrayJagged = new string[stringArray2D.GetLength(0)][];
int length2 = stringArray2D.GetLength(1);
for (int i = 0; i < arrayJagged.Length; i++)
{
arrayJagged[i] = new string[length2];
for (int j = 0; j < length2; j++)
{
arrayJagged[i][j] = stringArray2D[i, j];
}
}
Note that you don't really need a List<List<string>>
because in the end the dimensions of the jagged array are predetermined.
Then you can .GroupBy()
the jagged array, and do a .Count()
on each group:
var grouped = arrayJagged.GroupBy(x => x, ArrayEqualityComparer<string>.Default)
.Select(x => new
{
x.Key,
Count = x.Count()
})
.ToArray();
Note that .NET doesn't have a default equality comparer for arrays, so you'll need to define one, to show the .GroupBy()
how to check for equality of elements:
// Simple T[] IEqualityComparer<>
public sealed class ArrayEqualityComparer<T> : IEqualityComparer<T[]>, IEqualityComparer
{
// One instance is more than enough
public static readonly ArrayEqualityComparer<T> Default = new ArrayEqualityComparer<T>();
// We lazily define it if necessary
private readonly IEqualityComparer<T> equalityComparer;
public ArrayEqualityComparer()
{
equalityComparer = EqualityComparer<T>.Default;
}
public ArrayEqualityComparer(IEqualityComparer<T> equalityComparer)
{
this.equalityComparer = equalityComparer;
}
/* IEqualityComparer<T[]> */
public bool Equals(T[] x, T[] y)
{
if (x == null)
{
if (y == null)
{
return true;
}
return false;
}
if (y == null)
{
return false;
}
return EqualsNotNull(x, y);
}
public int GetHashCode(T[] obj)
{
unchecked
{
int hash = 17;
if (obj != null)
{
// This one will help distinguish between null and empty:
// hash(null) == 17, hash(empty) == 17 * 23
hash = (hash * 23) + obj.Length;
for (int i = 0; i < obj.Length; i++)
{
hash = (hash * 23) + obj[i].GetHashCode();
}
}
return hash;
}
}
/* IEqualityComparer */
bool IEqualityComparer.Equals(object x, object y)
{
if (x == y)
{
return true;
}
if (x == null || y == null)
{
return false;
}
var x2 = x as T[];
if (x2 == null)
{
throw new ArgumentException("x");
}
var y2 = y as T[];
if (y2 == null)
{
throw new ArgumentException("y");
}
return EqualsNotNull(x2, y2);
}
int IEqualityComparer.GetHashCode(object obj)
{
T[] obj2;
if (obj != null)
{
obj2 = obj as T[];
if (obj2 == null)
{
throw new ArgumentException("obj");
}
}
else
{
obj2 = null;
}
return GetHashCode(obj2);
}
/* Implementation */
private bool EqualsNotNull(T[] x, T[] y)
{
if (x.Length != y.Length)
{
return false;
}
if (x.Length != 0)
{
for (int i = 0; i < x.Length; i++)
{
if (!equalityComparer.Equals(x[i], y[i]))
{
return false;
}
}
}
return true;
}
}