在一个网格中给定一个位置,它所在的行和列分别是多少?

3
我正在编写一个应用程序,需要将街道地址放在预定义的标签纸上。该标签纸有3列和10行。我已经正确创建了生成标签的循环,但是要求允许用户选择从哪个标签开始。我原以为这是一个简单的数学矩阵方程,但我无法想出或找到解决方案。
以下是示例:
1   2  3  4  5
6   7  8  9 10
11 12 13 14 15 

假设给定上面的矩阵,用户决定从#6开始。我需要能够告诉我的循环从该位置开始:列:1行:2。

如果有帮助的话,我拥有的循环看起来像这样,但我认为这归结于我没有考虑的数学方程:

for (var yCounter = 0; yCounter < _labelSettings.LabelPerColumn; yCounter++)
{
    for (var xCounter = 0; xCounter < _labelSettings.ColumnsPerPage; xCounter++)
    {       
        foreach (var table in customNugget.PdfTables)
        {
            table.YPosition = SheetSettings.PageHeight -
                              (verticalOffset + yCounter * ((verticalSize + verticalOffset)));

            table.XPosition = horizontalOffset + xCounter * ((horizontalSize + horizontalOffset));
        }
    }
}

编辑

     private static int _cellsPerRow = 3;
    private static int _startIndex;

    static void Main(string[] args)
    {

        string userInput = Console.ReadLine();
        _startIndex = int.Parse(userInput);

        int startY = _startIndex / _cellsPerRow;
        int startX = (_startIndex - 1) % _cellsPerRow;

        Console.WriteLine(string.Format("The index you chose lives in the following matrix location:\n Row: {0} Column: {1}", startY, startX));
        Console.WriteLine("Press any key to continue...");
        Console.Read();

    }

你能不能把数字除以列数得到行数,然后用余数移动到正确列的位置呢?希望我解释得足够清楚了... - Sorceri
抱歉Sorceri,也许我误解了您的意思,但是它在数字9上起作用,但让我们拿数字4来说吧。我的矩阵有3列,10行(或30个可能的标签),如果我将30除以4,得到7.5。数字4的列和行分别为1和2,所以这不起作用。 - gcoleman0828
你不会按行来除,而是按列来除以得到行数,如4/3,则为1行余1列。我解释的是你接受的答案,只是显然没有讲好。 ;) - Sorceri
4个回答

4

假设你知道每行单元格的数量(我认为应该是_labelSettings.ColumnsPerPage),你可以这样计算起始值:

int cells = 5;//number of cells per row
int startAt = 6;//cell number to start at

int startY = (startAt - 1) / cells;//1
int startX = (startAt - 1) % cells;//0

您可以使用这些起始值来初始化循环,但是需要注意确保内部循环仅在第一次运行时使用计算出的起始值。为此,您只需在 y 循环的第一次执行后重置 startX 即可。操作如下:

for (var yCounter = startY; yCounter < _labelSettings.LabelPerColumn; yCounter++)
{
    for (var xCounter = startX; xCounter < _labelSettings.ColumnsPerPage; xCounter++)
    {
        //do stuff
    }
    startX = 0;//reset so that the next execution starts at the beginning of the row
}

这里是逻辑的证明,尽管是用JavaScript编写的

编辑:计算startY的方法已经修改,以正确处理从一行中的最后一个数字开始(感谢@Zach指出错误)


感谢您的帮助。我无法使Fiddler运行(我很少使用它,所以我不确定除了点击运行之外还需要做什么),但我已经更新了我的问题,并尝试了一些方法,有时候可以工作,有时候不行。我错过了什么吗?当我输入11时,应该是第4行第1列(如果从1开始而不是0,则为第2列)。 - gcoleman0828
1
@gcoleman0828:我的代码使用从零开始的索引,因为这是您的循环所需的。在您的示例网格中有3行5列。那么11应该是第3行和第1个单元格。我的代码将正确生成2和0(从零开始)。JSFiddle要求您打开控制台以查看输出结果(在Chrome中:CTR + SHIFT + J)。 - musefan
我的错误,你是正确的。我数错了行数。我一直在想为什么列总是正确,但行数却少了1..哈哈..谢天谢地今天是星期五。这就是我能说的!而且是从0开始计数,@Tim下面的是从1开始计数,所以不适用。你有没有任何材料或者知道任何网上可以解决这种方程的资料,这样我就可以稍微研究一下并学习它?我认为这与矩阵计算有关,但我研究的所有内容都没有揭示这种类型的问题。再次非常感谢。 - gcoleman0828
我是不是漏掉了什么,还是这个答案是错误的?如果你从一个恰好是列数的完全除数的数字开始呢?比如上面的例子中的5。在这种情况下,y会偏移一个。你应该得到starty(row)=0和startx(col)=4,但实际上你得到的是starty(row)=1和startx(col)=4。 - Zach
@Zach:发现得好,我已经更新了我的答案来解决这个问题。 - musefan

1
这适用于基于1的值,就像你在问题中展示的那样:
int _cellsPerRow = 5; //number of cells per row
for (int startAt = 1; startAt <= 15; startAt++)
{
    int startY = (startAt - 1) / _cellsPerRow + 1;
    int startX = (startAt - 1) % _cellsPerRow + 1;
    Console.WriteLine("{0}: {1}, {2}", startAt, startX, startY);
}

(e.g., "6: 1, 2")


谢谢Tim...你能给我指一些数学网站的资料吗?这样我就可以理解你是从哪里得出这个结论的,以及如何在未来解决类似的问题。我喜欢学习而不是简单地复制。 - gcoleman0828
@gcoleman0828 其核心是 index / _cellsPerRow,使用整数除法和 index % _cellsPerRow,使用模运算符。您可以查阅这些术语以获取更多详细信息,但基本上我意识到(感谢Ryxuma的解决方案)这些将为您提供所需的行/列值,但输入和输出为0。然后,根据需要添加和减去1(我打印出整个列表并查看了哪些不正确)以获取所需的值。 - Tim S.
谢谢@Tim。我想我的问题是为什么'y'是除法而'x'是模数? - gcoleman0828
因为从a == 0开始,a / b(递增a)将返回重复b次的0,然后是重复b次的1,以此类推。这恰好与从0开始计算行数(y)时所需的计数方式相同。而从a == 0开始,a % b将返回0b-1,然后循环回到0并重新开始。这恰好与从0开始计算列数(x)时所需的计数方式相同。 - Tim S.
换句话说:如果将 a * b 视为计算一个宽为 a,高为 b 的矩形中的项目数量,那么整数除法 a / b 就是在将 a 个项目排列成 b 列时计算完整行数的数量,而 a % b 则是在将 a 个项目排列成 b 列时计算最后一行未满的项目数量。 - Tim S.

1
x = num % grid width

y = num / grid width

num是起始数字 %是模运算符(除法后的余数) grid width是网格宽度 :)


0
一个更通用的方法是将要跳过的数字打印为空标签。如果你没有像上面那样的控制权,只需生成带有6个空标签的数据。每次都可以使用。

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