C# 多维数组行

Posted

技术标签:

【中文标题】C# 多维数组行【英文标题】:C# rows of multi-dimensional arrays 【发布时间】:2012-03-24 07:29:02 【问题描述】:

在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# 中使用矩形和锯齿状数组的好处?这是否发生在其他流行的编程语言中? (爪哇?) 感谢所有的帮助!

【问题讨论】:

【参考方案1】:

不能传一行的矩形数组,必须使用交错数组(数组的数组):

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:不,你不能 所以基本上这不是一个解决方案:)【参考方案2】:

你没有,像这样的rectangular array。这是一个单一的对象。

相反,您需要使用jagged array,如下所示:

// 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如果您对此不确定,不妨阅读我在parameter passing in C# 上的文章。

【讨论】:

你秒杀我! :P 我可以将矩形数组作为锯齿状数组传递吗? 在我看来,这似乎不是一个解决方案。矩形阵列的情况下可以做什么? @NielsAbildgaard:基本上没什么。问题的答案是“你不能那样做”。这可能不是 OP 想听到的答案,但它是正确的答案。 @NielsAbildgaard:您不能将其作为数组传递,而这正是 OP 似乎正在寻找的。您可以创建自己的包装器类型,但没有迹象表明这会对 OP 有所帮助。但是,如果您认为自己有更好的答案,为什么不自己添加呢?【参考方案3】:

更新:正如 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) 的结果不属于变量,因此无法编译代码。您只是不能将矩形数组视为锯齿状数组 - 数组不能那样工作。 我不明白您对编译的评论。代码运行并编译。 你完全正确!这不会传递对行的引用(无法完成)。假设 FindLeast 没有修改该行,这应该可以工作。不过,我将重命名该方法:) 它可以解决 OP 的 FindLeast 示例,但它没有解决将矩形数组的单行作为一维数组传递的更普遍的问题,这是(我一直在说)不可能的。 老实说,我认为这是隐含的。 “传递一行多维数组”和“传递一行多维数组的副本”是两个不同的东西。我认为说“你不能通过一行”比声称你可以,实际上只是通过一个副本要清楚得多。我仍然认为对 OP 问题的最佳答案是“你不能”。

以上是关于C# 多维数组行的主要内容,如果未能解决你的问题,请参考以下文章

多维数组和 C# 中的数组数组有啥区别?

C# 中的多维数组列表或列表?

C#多维数组转换成数组[重复]

C#多维数组与嵌套数组

c# 多维数组交错数组(转化为DataTable)

C# 中的多维关联数组