如何在 C# 中获取对多维数组的单个维度的引用?

发布于 2024-09-28 04:56:35 字数 626 浏览 0 评论 0原文

我遇到了一个问题,我想创建一个数组表。这是一个二维数组,在需要创建表之前,行数和列数在运行时已知。所有行的列数都相同。

创建数组后,我只想对该数组的一维进行操作。也许传递对方法的引用。

这是一个虚构的示例:

// Create a table 3x3 table.
int[,] DistanceTable = new int[3, 3];
DistanceTable[0, 0] = 0;
DistanceTable[1, 1] = 0;
DistanceTable[2, 2] = 0;

DistanceTable[0, 1] = 10;
DistanceTable[0, 2] = 40;

DistanceTable[1, 0] = 10;
DistanceTable[1, 2] = 25;

DistanceTable[2, 0] = 40;
DistanceTable[2, 1] = 25;

// Why can't I do this?
int[] twos = DistanceTable[2];

如果我要使用 JaggedArray(数组的数组),它可以让我这样做。但我不需要 JaggedArray,因为我的多维数组每行始终具有相同的列数。

可以这样做吗?如果不是为什么?

谢谢

I've come across a problem where I'd like to create an Array table. That is a 2 dimensional array where the number of rows and columns are known at runtime before the table needs to be created. The number of columns is the same for all rows.

Once the array is created I'd like to operate on just 1 dimension of that array. Perhaps pass a reference to an method.

Here is a fictional example:

// Create a table 3x3 table.
int[,] DistanceTable = new int[3, 3];
DistanceTable[0, 0] = 0;
DistanceTable[1, 1] = 0;
DistanceTable[2, 2] = 0;

DistanceTable[0, 1] = 10;
DistanceTable[0, 2] = 40;

DistanceTable[1, 0] = 10;
DistanceTable[1, 2] = 25;

DistanceTable[2, 0] = 40;
DistanceTable[2, 1] = 25;

// Why can't I do this?
int[] twos = DistanceTable[2];

If I were to use a JaggedArray (Array-of-Arrays) it lets me do this. But I don't need a JaggedArray because my multidemsional array always has the same number of columns for each row.

Is it possible to do this? If not why?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

沧桑㈠ 2024-10-05 04:56:35

否。多维数组与交错数组的不同之处在于,多维数组使用 Row 按顺序存储在一块内存中-主要订购

因此,拉出一“列”数据需要跳过才能将其拉出。

另一方面,锯齿状数组是对第二个数组的引用的数组。这使得从锯齿状数组中取出单独的“数组”变得容易。

但我不需要 JaggedArray,因为我的多维数组每行始终具有相同的列数。

.NET 中的锯齿状数组具有一些巨大的性能优化。它们的性能通常优于多维数组。这就是为什么大多数代码分析例程会建议从二维数组转换为锯齿状数组。即使您“不需要”它,也值得考虑这一点。

No. Multidimensional arrays differ from Jagged arrays in that they are stored sequentially, in one block of memory, using Row-Major ordering.

Because of this, pulling out one "column" of data requires skipping in order to pull this out.

Jagged arrays, on the other hand, are an array of references to a second array. This makes it easy to pull out individual "arrays" from the jagged array.

But I don't need a JaggedArray because my multidemsional array always has the same number of columns for each row.

Jagged arrays in .NET have some huge performance optimizations. They often outperform multidimensional arrays. This is why most code analysis routines will suggest conversion to a jagged array from a two dimensional array. It would be worth considering this even if you don't "need" it.

苏大泽ㄣ 2024-10-05 04:56:35

这是不可能的;多维数组则不然。

一般来说,您应该始终使用锯齿状数组;他们更快。
(JITter 将生成原始内存访问指令而不是方法调用)

This is not possible; multi-dimensional arrays do not work like that.

In general, you should always use jagged arrays; they're faster.
(The JITter will generate raw memory access instructions instead of method calls)

红颜悴 2024-10-05 04:56:35

多维数组只有一个数组对象,而锯齿数组是多个不同数组对象的嵌套。不存在 1-1 匹配或提取方法(不涉及使用包装器)。

There is only one array object with a multidimensional array whereas a a jagged array is a nesting of multiple distinct array objects. There is not a 1-1 match-up or method of extraction (that does not involve using a wrapper).

昵称有卵用 2024-10-05 04:56:35

抱歉,这确实应该是对 如何在 C# 中获取对多维数组的单个维度的引用? 但我还不允许发表评论..

无论如何,经过一些解释后,交错数组性能更好的原因很容易理解:让我们检查一个多维数组:

{{0, 1, 2},
{3,4,5},
{6, 7, 8}}

在内存中存储的内容如下:{0, 1, 2, 3, 4, 5, 6, 7, 8}。

现在,假设您要访问 [0, 0],我们要读取内存中的哪个位置?我们必须计算地址:y * 3 + x => 0 * 3 + 0 => 0. 之后,我们可以继续进行实际的阅读。如果我们想读整行,我们就必须一遍又一遍地做这个数学运算。

相反,看看一个锯齿状数组,在内存中它存储的内容如下:

a: {0, 1, 2}
乙:{3,4,5}
丙:{6,7,8}
{ref: a, ref:b, ref:c}

假设我们要访问 [0][0],我们要读取内存中的哪里?首先,让我们获取对数组[0]的引用。然后获取单元格[0]的内容。完毕。如果我们想读取整行,只需将指针加一即可。

如果我们要迭代整个“数组”而不是仅仅一行,那么对于锯齿状数组来说,它仍然具有相同的性能优势。

但有一个例外:迭代列。这对于锯齿状数组来说确实很糟糕,因为我们将为每次访问执行相对昂贵的内存读取。不好。

如果您觉得这是一个问题,那么还有一种方法:一维数组!在本例中,我们使用多维数组 (y * rowLength + x) 背后的理论,并使用一些非常简单的数学;要迭代行:只需增加 1,迭代列:只需增加 rowLength。

I'm sorry, this should really be a comment to How do I get a reference to a single dimension of a Multidemensional Array in C#? but I'm not allowed to comment yet..

Anyway, the reason to why the performance is better with a jagged array is easy to understand after some explanation: Let's examine a multidimensional array:

{{0, 1, 2},
{3, 4, 5},
{6, 7, 8}}

In memory it's stored something like this: {0, 1, 2, 3, 4, 5, 6, 7, 8}.

Now, suppose you want to access [0, 0], where in memory are we going to read? We have to calculate the address: y * 3 + x => 0 * 3 + 0 => 0. After that, we can go on and do the actual read. In case we want to read the whole line, we have to do this math over and over again.

Instead, look at a jagged array, in memory it's stored something like this:

a: {0, 1, 2}
b: {3, 4, 5}
c: {6, 7, 8}
{ref: a, ref:b, ref:c}

Suppose we want to access [0][0], where in memory are we going to read? First, let's get a reference to array [0]. And then get the content of cell [0]. Done. In case we want to read the whole line, we only need to increment the pointer by one.

If we are going to iterate through the whole "array" instead of just one row, it's still the same performance benefit for jagged arrays.

There's one exception though: iterate columns. That's really bad for jagged arrays since we are going to do a relative expensive memory-read for each and every access. Not good.

If you feel that it's a problem there's one method left: A one-dimensional array! In this case we use the theory behind the multidimensional array (y * rowLength + x), and use some really simple math; To iterate a row: just increment by one, to iterate a column: just increment by rowLength.

风渺 2024-10-05 04:56:35

您可以在 DictionaryTable 对象上创建一个扩展方法,以允许您指定行?

public static class IntArrayExt
{
    public static int[] Row(this int[,] array, int row)
    {
        int[] newArray = new int[3];
        for (int i = 0; i < array.Length; i++)
        {
            newArray[i] = array[row, i];
        }
        return newArray;
    }
}

int[,] distanceTable = new int[3, 3];
distanceTable[0, 0] = 0;
distanceTable[1, 1] = 0;
distanceTable[2, 2] = 0;

distanceTable[0, 1] = 10;
distanceTable[0, 2] = 40;

distanceTable[1, 0] = 10;
distanceTable[1, 2] = 25;

distanceTable[2, 0] = 40;
distanceTable[2, 1] = 25;

int[] twos = distanceTable.Row(2);

如果你想获得一列,你可以创建另一个扩展方法。

You could make an extension method on your DictionaryTable object that allows you to specify the row?

public static class IntArrayExt
{
    public static int[] Row(this int[,] array, int row)
    {
        int[] newArray = new int[3];
        for (int i = 0; i < array.Length; i++)
        {
            newArray[i] = array[row, i];
        }
        return newArray;
    }
}

int[,] distanceTable = new int[3, 3];
distanceTable[0, 0] = 0;
distanceTable[1, 1] = 0;
distanceTable[2, 2] = 0;

distanceTable[0, 1] = 10;
distanceTable[0, 2] = 40;

distanceTable[1, 0] = 10;
distanceTable[1, 2] = 25;

distanceTable[2, 0] = 40;
distanceTable[2, 1] = 25;

int[] twos = distanceTable.Row(2);

You could make another extension method if you want to get a column.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文