【问题标题】:JavaScript: Automatically order a variable multi-dimensional array diagonallyJavaScript:自动对可变多维数组进行对角排序
【发布时间】: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 对角线

标签: javascript jquery arrays math multidimensional-array


【解决方案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 &gt;= rows),它将运行“行”次。

现在,正确的边界。如果我们查看右侧的哪些对角线比“rows”短,我们将看到所有对角线都大于“cols”(在 cols 为 10、0 索引的示例中,即第 10 行及以后)。用j &gt;= Math.max(0, i - cols + 1) 替换j &gt;= 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 &lt; 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 代码有效,我只是想添加另一种方法。

    【讨论】:

      猜你喜欢
      • 2011-10-23
      • 2012-11-27
      • 2017-11-09
      • 1970-01-01
      • 2010-10-13
      • 1970-01-01
      相关资源
      最近更新 更多