C#多维数组的行

8
在C#编程语言中,如何传递多维数组的一行?例如,假设我有以下内容:
int[,] foo;
foo = new int[6,4];
int[] least;
least = new int[6];

for(int i = 0; i < 6; i++)
{
    least[i] = FindLeast(ref foo[i]);     //How do I pass the ith row of foo???
}

此外,有人能解释一下在C#中拥有矩形和锯齿数组的好处吗?其他流行的编程语言(比如Java)是否也有这种情况发生?谢谢大家的帮助!
3个回答

8

无法传递矩形数组的一行,您必须使用锯齿数组(数组的数组):

int[][] foo = new int[6][];

for(int i = 0; i < 6; i++)
    foo[i] = new int[4];

int[] least = new int[6];

for(int i = 0; i < 6; i++)
    least[i] = FindLeast(foo[i]);

编辑
如果您觉得使用锯齿数组很烦人,而且迫切需要一个矩形数组,那么一个简单的技巧可以帮助您:

int FindLeast(int[,] rectangularArray, int row)

我可以将一个矩形数组传递给接受锯齿数组的函数吗? - CodeKingPlusPlus
1
@CodeKingPlusPlus:不,你不能。 - BlackBear
所以基本上这不是一个解决方案 :) - Niels Abildgaard

4
你不能使用像这样的矩形数组。它是一个单一的对象。
相反,你需要使用不规则数组,就像这样:
// Note: new int[6][4] will not compile
int[][] foo = new int[6][];
for (int i = 0; i < foo.Length; i++) {
    foo[i] = new int[4];
}

然后您可以传递每个“子”数组:

int[] least = new int[foo.Length];
for(int i = 0; i < 6; i++)
{
    least[i] = FindLeast(foo[i]);
}

请注意,无需通过引用传递foo[i]1,在声明变量时赋值是一个好习惯,这样可以使代码更加简洁易懂。(这样做可以使您的代码更加紧凑和简单易懂。)

1 如果您对此不确定,您可能需要阅读我的文章C#中的参数传递


你比我快了几秒钟!:P - BlackBear
我可以将矩形数组作为锯齿数组传递吗? - CodeKingPlusPlus
1
这对我来说似乎不是一个解决方案。在矩形数组的情况下该怎么办? - Niels Abildgaard
1
@NielsAbildgaard:基本上什么都不能做。对于这个问题的答案是“你无法做到”。这可能不是提问者想听到的答案,但它是正确的答案。 - Jon Skeet
1
@NielsAbildgaard:你不能将它作为数组传递,这似乎是OP所寻求的。你可以创建自己的包装类型,但没有迹象表明这会对OP有所帮助。然而,如果你认为你有更好的答案,为什么不自己加呢? - Jon Skeet
显示剩余2条评论

-1

更新:正如Jon Skeet所指出的那样,这并不提供对行的引用,而是创建一个新副本。如果您的代码需要更改一行,则此方法无效。我已经将该方法重命名以明确这一点。

更新2:如果您想要能够编辑字段,并且还希望更改反映在父数组中,您可以使用我在this library I maed中提供的包装器。生成的行foo.Row(i)不是数组,而是实现了IList,因此如果您需要传递一个数组,则这也不是解决方案。


这个扩展方法将允许您查询多维数组的行。需要注意的是,这是计算上很重的(高效),如果可以的话,您应该使用锯齿形数组来处理这些情况。然而,如果您发现自己处于无法使用锯齿形数组的情况下,这可能会有用。

public static T[] CopyRow<T>(this T[,] arr, int row)
{
    if (row > arr.GetLength(0))
        throw new ArgumentOutOfRangeException("No such row in array.", "row");

    var result = new T[arr.GetLength(1)];
    for (int i = 0; i < result.Length; i++)
    {
        result[i] = arr[row, i];
    }
    return result;
}

你现在可以重写你的代码:

int[,] foo;
foo = new int[6,4];
int[] least;
least = new int[6];

for(int i = 0; i < 6; i++)
{
    least[i] = FindLeast(ref foo.CopyRow(i));
}

这只是复制数组内容,这并不是同样的事情。特别地,如果FindLeast修改了数组,则该修改在结果中将不可见。此外,foo.Row(i)的结果不被归类为变量,因此代码无法编译。你不能简单地将矩形数组视为锯齿数组 - 数组就不是这样工作的。 - Jon Skeet
1
它可能解决了OP的“FindLeast”示例,但它未能解决更一般的问题,即将矩形数组的单行作为一维数组传递,这是(正如我不断强调的)不可能的。 - Jon Skeet
1
我认为说实话这是隐含的。"传递多维数组的一行"和"传递多维数组的一行的副本"是两回事。我认为明确地说"你不能传递一行"比声称你可以并且实际上传递一个副本更清晰。我仍然坚持认为对于OP的问题最好的答案是"你不能"。 - Jon Skeet
“重写”代码没有使用你的 CopyRow 方法。它实际上似乎并没有以任何方式被重写。此外,传递到 ArgumentOutOfRangeException 构造器 的字符串顺序是错误的 - 参数名称应该放在第一位。 - kdbanman
那只是一个简单的打字错误 -- (Row -> CopyRow). 已经修复了。 - Niels Abildgaard
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接