Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# LINQ query on multidimensional array

How would I use the following LINQ query correctly? I want to create a one-dimensional array that contains only values that are greater than 5. I can't understand why it can't iterate over this multidimensional array, but if I use foreach, it actually iterates.

// Create an multidimensional array, then just put numbers into it and print the array.  
int[,] myArr = new int[5,6];
int rows = myArr.GetLength(0);
int cols = myArr.GetLength(1);
for (int i = 0; i < rows; i++)
{
    for (int k = 0; k < cols; k++)
    {
        myArr[i,k] = i + k;
        Console.Write(myArr[i,k]);
    }
    Console.WriteLine("");

}

var highList = from val in myArr where (val > 5) select val;

The error is:

Could not find an implementation of the query pattern for source type 'int[*,*]'. 'Where' not found. Are you missing a reference or a using directive for 'System.Linq'?

I thought this might fix the problem:

public static IEnumerator<int> GetEnumerator(int[,] arr)
{
    foreach(int i in arr)
    {
        yield return i;
    }
}

But it doesn't implement the iterator.

like image 332
user3604597 Avatar asked Dec 26 '22 01:12

user3604597


1 Answers

The problem is that multi-dimensional (rectangular) arrays implement IEnumerable, but not IEnumerable<T>. Fortunately, you can use Cast to fix that - and Cast gets called automatically if you explicitly specify the type of the range variable:

var highList = from int val in myArr where (val > 5) select val;

Or without the unnecessary brackets:

var highList = from int val in myArr where val > 5 select val;

Or using method calls directly, given that it's a pretty trivial query expression:

var highList = myArr.Cast<int>().Where(val => val > 5);

I think this will box each element, however. You could add your own Cast extension method to avoid that:

public static class RectangularArrayExtensions
{
    public static IEnumerable<T> Cast<T>(this T[,] source)
    {
        foreach (T item in source)
        {
            yield return item;
        }
    }
}
like image 93
Jon Skeet Avatar answered Dec 27 '22 17:12

Jon Skeet