I want to write some logic in c# for two multidimensional arrays. I know that I can use SequenceEqual to verify and return true if they are in the same order How would I still return true, if the arrays inside the multidimensional array had elements in different locations?
using System;
using System.Collections;
using System.Linq;
class Program {
public static void Main (string[] args) {
string[,] actual = new string[,]
{
{"fruitname", "fruitcolor", "fruitshape"},
{"banana", "yellow", "rectangle"},
{"apple", "red", "round"}
};
string[,] user1 = new string[,]
{
{"fruitname", "fruitcolor", "fruitshape"},
{"banana", "yellow", "rectangle"},
{"apple", "red", "round"}
};
string[,] user2 = new string[,]
{
{"fruitshape", "fruitname", "fruitcolor"},
{"rectangle", "banana", "yellow"},
{"round", "apple", "red"}
};
Console.WriteLine(VerifyQueries(actual, user2));
}
public static bool VerifyQueries(string[,] storedQuery, string[,] userQuery) {
// Check length & number of elements in the array
if(storedQuery.Rank == userQuery.Rank &&
Enumerable.Range(0,storedQuery.Rank)
.All(dimension => storedQuery.GetLength(dimension) == userQuery.GetLength(dimension))
)
{
// Check if they are exactly the same, return true
if(storedQuery.Cast<string>().SequenceEqual(userQuery.Cast<string>())) {
return true;
}
//Check if they have matching elements in different index
for(int i = 0; i < storedQuery.GetLength(0); i ) {
for(int j = 0; j < storedQuery.GetLength(1); j ) {
}
}
}
return false;
}
}
currently, I am returning true for actual and user1 arrays. I want to return true also for actual and user2.
CodePudding user response:
I think you could flatten the arrays to 1D array then sort them and compare as you are doing in your code.
var storedFlat = storedQuery.Cast<string>().OrderBy(x => x).ToArray();
var userFlat = userQuery.Cast<string>().OrderBy(x => x).ToArray();
return storedFlat.SequenceEqual(userFlat);
CodePudding user response:
Something like this should work:
public static bool VerifyQueries(string[,] storedQuery, string[,] userQuery)
{
// Check length & number of elements in the array
if (storedQuery.Rank != userQuery.Rank ||
Enumerable.Range(0, storedQuery.Rank).Any(dimension => storedQuery.GetLength(dimension) != userQuery.GetLength(dimension)))
{
return false;
}
// Check if they are exactly the same, return true
if (storedQuery.Cast<string>().SequenceEqual(userQuery.Cast<string>()))
{
return true;
}
static IEnumerable<string> row(string[,] array, int r) // Convenience method to return elements of one row.
{
for (int i = 0; i < array.GetLength(1); i)
{
yield return array[r, i];
}
}
//Check if they have matching elements in different index
for (int i = 0; i < storedQuery.GetLength(0); i )
{
if (row(storedQuery, i).Except(row(userQuery, i)).Any())
return false;
}
return true;
}
Notes:
- I've changed the dimension check so that it returns
false
at the start of the method, to avoid unnecessary indentation. - I've added a local method to enumerate the elements of one row - this simplifies the code somewhat.
- I'm checking if two rows differ by using
.Except()
. This will return an empty sequence if the two rows are identical ignoring order, or a non-empty sequence if the two rows contain different elements. Then I can use.Any()
to determine if we need to returnfalse
(because a non-empty result means that the rows contain different elements). - This uses
.Except()
rather than sorting, meaning it hasO(N)
complexity rather thanO(N.Log(N))