JavaScript:自动对可变多维数组进行对角排序
Posted
技术标签:
【中文标题】JavaScript:自动对可变多维数组进行对角排序【英文标题】:JavaScript: Automatically order a variable multi-dimensional array diagonally 【发布时间】:2011-08-15 13:36:46 【问题描述】:这更像是一道数学题。
我正在尝试使用 jQuery 创建一个可爱的淡入淡出效果,通过将一个元素拆分为一定数量的块,然后淡化每个块,但基于另一个数组延迟淡化效果。
所以要创建块表,我有两个变量:
var rows = 4,
cols = 10;
这会将元素分成如下块:
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
然后我创建另一个数组来决定块的动画效果。例如,对于从左到右的对角线动画,这个数组看起来像:
order = [0, 10, 1, 20, 11, 2, 30, 21, 12, 3, 31, 22, 13, 4, 32, 23, 14, 5, 33, 24, 15, 6, 34, 25, 16, 7, 35, 26, 17, 8, 36, 27, 18, 9, 37, 28, 19, 38, 29, 39];
对于这种特定情况,它可以工作:D
我的问题是如何根据可以更改的块数(行 x 列)自动而不是手动创建 order
数组?
谢谢
【问题讨论】:
是否总是用于从左到右的对角线动画? 不,我也想做这个 r-t-l 对角线,或者从中心旋转等。但是现在我想了解如何在这种情况下做到这一点,l-t-r 对角线 【参考方案1】:这样就可以了:
var arr = [];
var rows = 4;
var cols = 10;
for(var i = 0; i < rows + cols - 1; i++)
for(var j = Math.min(rows, i + 1) - 1; j >= Math.max(0, i - cols + 1); j--)
arr.push((j * cols) + i - j);
小提琴:http://jsfiddle.net/BmXpy/
编辑:这是我试图解释我是如何想到这个的。重要的是,使用上面的数字表进行可视化,如果需要,打印出来并画出对角线。
首先,想想我们想要什么,它基本上是对角线。在上面的例子中,第一个对角线是 0,然后是 10、1,然后是 20、11、2,然后是 30、21、12、3,等等。现在如果你想想这些对角线有多少,它是 @987654323 @。这就是我们得到第一个循环的地方:
for(var i = 0; i < rows + cols - 1; i++)
现在,暂时忽略边界。在一般情况下(整个中心),这些对角线中的每一个都是“行”长。由于我们想要自下而上,我们想要一个反向循环。内部循环看起来像这样:
for(var j = rows - 1; j >= 0; j--)
现在,我们必须处理两个边界(左边界和右边界)。
对于左边界,如果我们查看长度小于“行”的对角线的数量,我们会看到它是rows - 1
。对于这些对角线,我们将看到每个对角线的长度为i + 1
。以下内部循环将处理一般情况和左边界:
for(var j = Math.min(rows, i + 1) - 1; j >= 0; j--)
您会看到,对于对角线 0,它将运行一次,对于 1,它将运行两次,依此类推。对于一般情况 (i >= rows
),它将运行“行”次。
现在,正确的边界。如果我们查看右侧的哪些对角线比“rows”短,我们将看到所有对角线都大于“cols”(在 cols 为 10、0 索引的示例中,即第 10 行及以后)。用j >= Math.max(0, i - cols + 1)
替换j >= 0
对于一般情况和左边界将运行到0,但对于右边界会缩短。我们得到这个:
for(var j = Math.min(rows, i + 1) - 1; j >= Math.max(0, i - cols + 1); j--)
最后,实际计算每个位置的数量。 i
代表对角线,j
代表对角线上数字的索引 j = 0
是顶部数字,如果您正在查看已发布的数字表。对于j = 0
(顶行数字),数字就是i
,对于顶部以下的每一行,我们需要将数字乘以“cols”,以便得到第一行数字正下方的数字,然后数字需要向左调整。这是通过减去行号j
来完成的。所以对于j = 1
(第二行),我们需要将数字左移一(减1)。所以我们有i
用于第一行的水平位置,+ (j * cols)
将其向下移动到适当的行,然后 -j 将其调整为对角线(如果您绘制了对角线,请为其中一个跟踪以获得良好的视觉效果)。我们得到这个:
(j * cols) + i - j
把它们放在一起,你就得到了我上面的最终代码。希望这有点道理。
【讨论】:
@kingjiv:非常好!顺便说一下,建议使用 '[]' 而不是 'Array()' 漂亮!但请向我解释一下,i < rows + cols
之后我完全迷路了 :)
@diego 好点,已更新。试图改掉这个习惯。 @alex 我今晚回家后会整理一个解释。
@alex,编辑了我的答案,试图解释它。希望它在某种程度上有用。【参考方案2】:
还有另一种方法。
function diagonalized_block (rows, cols)
blocks = [];
for (var i = 0; i < rows * cols; i++)
blocks.push(i);
blocks.sort(function (a, b) return a/cols + a%cols - b/cols - b%cols);
return blocks;
这个想法很简单。写出所有块的明显数组,然后按照你想要的顺序按块的函数排序。该函数是x/cols + x%cols
。这是row + ascending error on diagonal + col
。所以你首先按照它们在哪个对角线上排序,然后在对角线上升序。
对于其他模式,您必须找到其他恰好可以正确排序的函数。 (或者编写一个更复杂的排序函数来完全按照您的意愿执行。)
【讨论】:
【参考方案3】:这里还有一个代码http://jsfiddle.net/paska/FhLnu/3/
var rows = 4,
cols = 10,
getValue = function(x, y)
return (y * cols) + x;
,
addValue = function(x, y)
$("#arr").append(getValue(x, y) + ", ");
,
max = rows + cols - 1,
updateRow = 0;
for(var i = 0; i < max; i++)
if(i >= rows)
updateRow++;
for(var x = 0; x <= i; x++)
//$("#arr").append(x + " " + (i - x) + "<br />");
var row = (i - x),
col = x;
if(updateRow)
row = row - updateRow;
col = col + updateRow;
if(col >= cols)
break;
if(row >= 0 && col >= 0)
addValue(col, row);
我知道@kingjiv 代码有效,我只是想添加另一种方法。
【讨论】:
以上是关于JavaScript:自动对可变多维数组进行对角排序的主要内容,如果未能解决你的问题,请参考以下文章