# Compare 2 dynamic jagged arrays of doubles and arrays of doubles

I want to be able to compare 2 jagged arrays of doubles for value equality. The arrays can have any number of dimensions. Inside any dimension could also be another array etc.

It is known that the values of any array dimension is a double, null or another array, so it should be able to compare any of these with one function:

• double[]
• double[][]
• double[][][]
• double[][double[]][double[][]]

public static bool ArraysEqual(dynamic a, dynamic b)
{
// Same objects or both null
if (ReferenceEquals(a, b)) return true;

// Just one object is null
if (a == null ^ b == null) return false;

// Different number of elements
if (a.Length != b.Length) return false;

// Array is empty
if (a.Length == 0) return true;

// Test each item in the arrays
for (int i = 0; i < a.Length; i++)
{
// Same object or both null
if (ReferenceEquals(a[i], b[i])) continue;

// Just one object is null
if (a[i] == null ^ b[i] == null) return false;

var aIsArray = a[i].GetType().IsArray;
var bIsArray = b[i].GetType().IsArray;

// Just one object is an array
if (aIsArray ^ bIsArray) return false;

// Both are arrays (no need to check b, since it was exclusive or'd prior)
// Stop evaluating if the recursive call returned false;
if (aIsArray)
{
if (!ArraysEqual(a[i], b[i])) return false;
}
else if (a[i] != b[i])
{
return false;
}
}

return true;
}


Nice question, and I am inspired to answer it, even though I don't use C#. I know enough about the algorithmic side to see a better way.

First though, the multitude of 1-liner if-conditions are bad practice. You should consider using braces even for these values.

The second thing, is the bitwise-XOR ^ operator you are doing in two places... this is conceptually broken, and unnecessary. A simple logical OR || comparison will be fine, since the previous check would return true if both values were null.

if (a == null || b == null)
{
return false;
}


The recursive system you have is a good option, but, if you change the 'recurse' point of the recursion, you will be able to do things in a more concise way. At the moment you are doing a number of the tests twice.

Have a look at the following:

public static bool ArraysEqual(dynamic a, dynamic b)
{
// Same objects or both null
if (ReferenceEquals(a, b))
{
return true;
}

// Just one object is null
if (a == null || b == null)
{
return false;
}

if (a.GetType().IsArray && b.GetType().IsArray)
{
if (a.Length == b.Length)
{
for (int i = 0; i < a.Length; i++)
{
if (!ArraysEqual(a[i], b[i]))
{
return false;
}
}
return true;
}
return false;
}

// fall back to simple value compare
return a == b;
}


Notice how, by doing the above, there is only one instance of each type of check.

I modified rolfl's code to work with value types.

    public static bool ArraysEqual(dynamic a, dynamic b)
{
// Same objects or both null
if (ReferenceEquals(a, b))
{
return true;
}

// Just one object is null
if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
{
return false;
}

if (a.GetType().IsArray && b.GetType().IsArray)
{
if (a.Length == b.Length)
{
for (int i = 0; i < a.Length; i++)
{
if (!ArraysEqual(a[i], b[i]))
{
return false;
}
}
return true;
}
return false;
}

// fall back to simple value compare
return Equals(a, b);
}