我不是c#专家,完全是LINQ初学者,在SO和Google中搜索了一下,没有发现如何做以下事情:
如果我有,比如说,int[10,10]
数组,我怎么能从它得到一个二维切片?
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;
}