二维数组的x、y和行、列属性是否颠倒?

67

如果我考虑平面直角坐标系,x和y是有序对的常见表示法,但是如果我使用一个二维数组,我会有myArray[row][col],其中row是y,col是x。这个顺序是错误的吗?还是我的想法有误?如果我想要真正的行和列(比如在游戏板上),那么myArray[x][y]是错误的。难道不应该是myArray[y][x]来真正模拟行列板吗?


2
我发现自己向父母问了同样的问题。很高兴知道没有标准。 - K-Dawg
8个回答

64
你说得对,这确实有点反常。行号是y坐标,列号是x坐标,但我们通常写行,列,而且我们通常写x,y。
无论你想将数组写成[y] [x]还是[x] [y],主要取决于你实际关心数组在内存中的布局程度(如果是的话,使用什么语言)。以及你是否想编写可以独立操作行或列的函数/方法。
如果你正在编写C / C ++代码,则数组存储在行优先顺序中,这意味着可以将单个数据行视为一维数组。但单个数据列不行。如果我记得正确的话,VB使用列优先顺序,因此语言各不相同。我会惊讶于C#不是行优先顺序,但我不知道。

2
这是我在搜索了20分钟后读到的最清晰的解释。 - FinancialRadDeveloper
C#是列优先的。检查方法:声明一个多维数组,例如int a[2, 2];在不安全的块中,固定第一个元素:fixed(int* p = &a[0,0]),并迭代int* q = p; q++每一步。如果数组被初始化为int[,] a = new int[2, 2] { { 1, 2 }, { 3, 4 } };你会看到1、2、3、4。如果它是行优先的,你会看到行维度(第一维)首先改变。 - ILoveFortran
2
@ILoveFortran,您的示例告诉我 C# 是行主序({1,2}是一行)。考虑到 C# 的血脉来自其他类 C 语言,行主序似乎更有可能。另请参见 https://stackoverflow.com/q/68049499/ 中的评论,其中解释了 CLI 指定使用行主序。 - jamesdlin
@jamesdlin,你是对的,我颠倒了行主序和列主序的定义。这个术语确实有问题。我想到的是列优先(列索引变化最快),这就是行主序。 - ILoveFortran

12

这是我为了保持自己的心智健康而做的事情:

int x = array[0].length;
int y = array.length;

然后对于我进行的每个数组调用,我都会编写:

array[y][x]

这对于绘制图形算法和水平/垂直矩阵翻转特别有用。


1
这个问题得到了很多点击量。有趣的是,这些年来情况如何变化。我得记住这个答案。谢谢。 - johnny

4
无论你是如何在数组中存储数据的([x][y]还是[y][x]),重要的是你总是以连续的方式循环遍历整个数组。一个Java二维数组本质上是一个一维数组,它存储了第二个数组(例如,在[y][x]的情况下,你有一个长为[y]的数组,其中每个y都包含相应的[x]数组)。
为了高效地遍历整个数组,重要的是以一种不需要在数组中不断搜索、从一个y数组的x数组跳到另一个y数组的x数组的方式访问数据。你想做的是访问一个y元素并访问其中所有的x,然后再移动到下一个y元素。
因此,在Array[y][x]的情况下,始终将外部循环中的第一个变量放在内部循环中的第二个变量之前:
for (int ys = 0; ys < Array.length; ys++)
    for (int xs = 0; xs < Array[y].length; xs++)
    {
        do  your stuff here
    }

当然,在循环之外预先分配两个数组长度,以防每个周期都需要获取这些值。


2

不管好坏,不一致的符号表示法是从数学中继承而来的。

多维数组遵循矩阵符号表示法,其中Mi,j代表第i行和第j列的矩阵元素。

因此,如果用于表示矩阵,则多维数组不是反向的,但如果用于表示二维笛卡尔平面,则它们似乎是反向的,其中(xy)是坐标的典型排序方式。

还要注意,二维笛卡尔平面通常是以y轴向上增长为方向。然而,这也与通常可视化2D数组/矩阵(以及大多数光栅图像的坐标系统)的方式相反。


2

我喜欢这个问题。你说得完全正确。大多数情况下,我们要么思考 (x, y) 要么思考 (row, col)。直到几年后我才开始质疑它。有一天我意识到,我总是将 for 循环处理为 x 是行,y 是列,尽管在平面几何中实际上是相反的。正如许多人所提到的,这在大多数情况下并不重要,但一致性是一件美妙的事情。


0
实际上,这取决于你。在你的问题中没有正确的思考方式。例如,我通常将一维数组看作是单元格的行。所以,在我的脑海中它是array[col][row]。但是这真的取决于你...

1
如果你在考虑缓存的后果,有一种正确的看待它的方式... - Michael Myers
@mmeyers:不完全是,其实这样做的效果就是把游戏棋盘横向存储。这种存储方式在图像处理中很常见。 - Joel
1
我认为这个问题没有给出任何上下文...当然在不同的上下文中,有不同的逻辑。 - anthares
@Joel: 1) 只要你在思考的方式上没有问题,无论是按列迭代还是按行迭代,只要能正确进行迭代即可。这可能需要你从(你的角度来看)按列而不是按行进行操作。2) 当你称呼我为mmeyers时,我并没有收到通知。自从通知功能实施以来,这已经是第四次发生这种情况了。 :) - Michael Myers

0

我敢打赌这个问题有很多不同的意见。底线是,只要你保持一致,它并不重要。如果你有其他库或类似的东西将使用相同的数据,为了更容易地集成,可能会有意义按照他们的方式进行。

如果这仅限于你自己的代码,请随意选择。我的个人偏好是使用myArray[y][x]。如果它们很大,将你要访问的项放在一起可能会带来性能上的好处。但是在非常晚的阶段(如果有的话)才考虑这个问题。


0
好吧,如果你把一行看作 x 轴上的元素,然后将二维数组看作许多行元素在 y 轴上,那么使用 y 来操作行是很正常的,因为你已经知道了该行的 x 值(对于特定的行来说,x 始终相同,而 y 则随其索引在变化),然后使用 x 操作多个行元素(这些行在垂直方向上叠放,每个行位于特定的 y 值上)。

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