2016-07-19 6 views
0

У меня возникла проблема, и я не уверен, что я что-то упустил или если это просто неуклюжий на C#.Сопоставление по двумерному массиву

У меня есть 2D-массив (Foo[,]), и я хочу его сопоставить с Bar[,], используя только Func<Foo, Bar>. В принципе, я хочу, чтобы экземпляр-функтор для T[,] для любого заданного T.

«Очевидный» способ - это, конечно же, просто построить новый массив с нуля, итерации по каждой колонке и столбцу и вручную применить функцию к ячейке. Я действительно хотел бы использовать LINQ для этого, хотя, потому что нет никаких оснований, это должно быть более сложным, чем

from cell in matrix 
select f(cell) 

или эквивалент matrix.Select(f).

Я не могу не думать, что я не могу быть первым, кто хотел это сделать, поэтому я задаюсь вопросом, есть ли что-то подобное встроенное, или лучше всего просто написать мои собственные расширения LINQ для 2D-массивы?

ответ

0

В .NET Framework отсутствуют методы LINQ, которые работают непосредственно с массивом 2d. Лучшее, что вы можете получить от встроенного кода - итерация по всем пунктам с помощью необщего IEnumerable с ручным Cast (Why do C# Multidimensional arrays not implement IEnumerable<T>?, Using Linq with 2D array, Select not found)

Как решение - написать свои собственные расширения или найти библиотеку.

+0

Написание кучи пользовательских расширений LINQ кажется самым простым и чистым путем. Нужно утомиться, чтобы писать и поддерживать такой шаблонный код, но хорошо. – kai

0

Не уверен, что это «лучший» способ (что бы это ни значило), но это работает как минимум. Может быть легко расширен, если вам нужно больше синтаксиса LINQ.

public static class Matrix 
{ 
    public static TResult[,] Select<T, TResult>(this T[,] source, Func<T, TResult> f) 
    { 
     var rows = source.GetLength(0); 
     var columns = source.GetLength(1); 
     var result = new TResult[rows, columns]; 

     for (var row = 0; row < rows; row++) 
     { 
      for (var column = 0; column < columns; column++) 
      { 
       result[row, column] = f(source[row, column]); 
      } 
     } 

     return result; 
    } 
} 

Протестировано, используя следующий (скорее недостаток-блеск) xunit факт, не стесняйтесь указывать на ошибки.

[Fact] 
public void MatrixSelect_GivenFunction_MapsMatrix() 
{ 
    var matrix = new[,] 
    { 
     {true, true}, 
     {false, true} 
    }; 

    var transformed = 
     from cell in matrix 
     select cell ? 1 : 0; 

    var expected = new[,] 
    { 
     {1, 1}, 
     {0, 1} 
    }; 
    Assert.Equal(expected, transformed); 
} 
Смежные вопросы