2016-07-19 90 views
0

我遇到了一个问题,我不确定我是否错过了某些东西,或者它在C#中真的很笨重。通过二维数组映射

我有一个二维数组(Foo[,]),我想要做的就是把它映射到一个Bar[,],使用只是一个Func<Foo, Bar>。基本上,我想要的是对于任何给定的TT[,]的仿函数实例。

“显而易见”的方式当然是从头开始构建一个新的数组,遍历每一列的行和列并手动将该函数应用于任何单元格。我真的想使用LINQ的针对这一点,因为没有任何理由,这应该是比

from cell in matrix 
select f(cell) 

或等值matrix.Select(f)更加复杂。

我不禁想到,我不能成为第一个想做这件事的人,所以我想知道是否有类似的内置内容,或者我最好只写自己的LINQ扩展二维数组?

回答

0

.Net Framework中没有LINQ方法直接与2d数组一起工作。通过非通用IEnumerable带手动CastWhy 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); 
}