【问题标题】:C# rows of multi-dimensional arraysC# 多维数组行
【发布时间】: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# 中使用矩形和锯齿状数组的好处?这是否发生在其他流行的编程语言中? (爪哇?) 感谢所有的帮助!

【问题讨论】:

    标签: c# arrays multidimensional-array row indices


    【解决方案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 问题的最佳答案是“你不能”。
    猜你喜欢
    • 2010-10-18
    • 2019-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多