使用c#中的LINQ从2D数组(int[,])中获取切片



我不是c#专家,完全是LINQ初学者,在SO和Google中搜索了一下,没有发现如何做以下事情:

如果我有,比如说,int[10,10]数组,我怎么能从它得到一个二维切片?

例如,如果上述数组中的值依赖于它们的位置(a[2,3] = 23, a[4,8] = 48,等等),我想执行以下伪代码:
int[3,3] a_slice = slicer_method(a, 3, 6, 2, 5)   // or anything equivalent to this
> [[ 32, 33, 34],
   [ 42, 43, 44],
   [ 52, 53, 54]]

它没有特别使用LINQ,但我看到LINQ在我最近遇到的每一个类似的操作中使用。

@JaredPar是正确的,没有内在的方法来执行切片—也就是说,您可以编写一个扩展方法来完成:

public static class Ext
{
    public static T[] Slice<T>(this T[] source, int fromIdx, int toIdx)
    {
        T[] ret = new T[toIdx - fromIdx + 1];
        for(int srcIdx=fromIdx, dstIdx = 0; srcIdx <= toIdx; srcIdx++)
        {
            ret[dstIdx++] = source[srcIdx];
        }
        return ret;
    }
    public static T[,] Slice<T>(this T[,] source, int fromIdxRank0, int toIdxRank0, int fromIdxRank1, int toIdxRank1)
    {
        T[,] ret = new T[toIdxRank0 - fromIdxRank0 + 1, toIdxRank1 - fromIdxRank1 + 1];
        for(int srcIdxRank0=fromIdxRank0, dstIdxRank0 = 0; srcIdxRank0 <= toIdxRank0; srcIdxRank0++, dstIdxRank0++)
        {        
            for(int srcIdxRank1=fromIdxRank1, dstIdxRank1 = 0; srcIdxRank1 <= toIdxRank1; srcIdxRank1++, dstIdxRank1++)
            {
                ret[dstIdxRank0, dstIdxRank1] = source[srcIdxRank0, srcIdxRank1];
            }
        }
        return ret;
    }
}

和一个测试:

void Main()
{
    var singleArr = new int[]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
    singleArr.Slice(2, 4).Dump();
    var doubleArr = new int[,]
    {
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
        { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
    };  
    doubleArr.Slice(2, 4, 2, 4).Dump();
}

在CLR上没有办法做到这一点,因为它不支持数组切片的概念。最好是在数组上创建一个包装器类型,模拟切片

您可以尝试这样做:

public T[,] Slice<T>(T[,] a, int x1, int y1, int x2, int y2)
{
    var result = new T[x2 - x1, y2 - y1];
    for (var i = x1; i < x2; i++)
    {
        for (var j = y1; j < y2; j++)
        {
            result[i - x1, j - y1] = a[i,j];
        }
    }
    return result;
}
示例

  public class MyArraySlice<T>  where T:struct {
    public MyArraySlice(T[,] array, int xMin, int xMax, int yMin, int yMax) {
      Array = array;
      XMin = xMin; XMax = xMax;
      YMin = yMin; YMax = yMax;
    }
    public T this[int i, int j] { get {
        if (XMin <= i && i < XMax  && YMin <= j && j < YMax)
          return Array[i+XMin, j+YMin];
        throw new ArgumentOutOfRangeException();
      }
    }
    T[,] Array;
    int XMin;
    int XMax;
    int YMin;
    int YMax;
  }

相关内容

  • 没有找到相关文章

最新更新