交错数组元素

时间:2012-02-22 02:22:09

标签: javascript

interleave的快速而简单的实施是什么:

console.log( interleave([1,2,3,4,5,6]      ,2) ); // [1,4,2,5,3,6]
console.log( interleave([1,2,3,4,5,6,7,8]  ,2) ); // [1,5,2,6,3,7,4,8]
console.log( interleave([1,2,3,4,5,6]      ,3) ); // [1,3,5,2,4,6]
console.log( interleave([1,2,3,4,5,6,7,8,9],3) ); // [1,4,7,2,5,8,3,6,9]

这模仿了数组并将其分成 n 相等的部分,然后按顺序将项目从每个部分数组的前面移开。 ( n = 2模拟了一副纸牌的完美减半和单次洗牌。)

我并不太关心当数组中的项目数不能被 n 整除时会发生什么。合理的答案可能是交错剩余的,甚至是“平底船”,并将它们全部扔到最后。

7 个答案:

答案 0 :(得分:2)

function interleave( deck, step ) {
    var copyDeck = deck.slice(),
        stop = Math.floor(copyDeck.length/step),
        newDeck = [];    
    for (var i=0; i<step; i++) {
        for (var j=0; j<stop; j++) {
            newDeck[i + (j*step)] = copyDeck.shift();
        }        
    }
    if(copyDeck.length>0) {
        newDeck = newDeck.concat(copyDeck);
    }
    return newDeck;
}

可以使用计数器而不是shift()

来完成
function interleave( deck, step ) {
    var len = deck.length,
        stop = Math.floor(len/step),
        newDeck = [],
        cnt=0;
    for (var i=0; i<step; i++) {
        for (var j=0; j<stop; j++) {
            newDeck[i + (j*step)] = deck[cnt++];
        }        
    }
    if(cnt<len) {
        newDeck = newDeck.concat(deck.slice(cnt,len));
    }
    return newDeck;
}

而不是将额外内容附加到最后,我们可以使用ceil并在用完时退出

function interleave( deck, step ) {
    var copyDeck = deck.slice(),
        stop = Math.ceil(copyDeck.length/step),
        newDeck = [];    
    for (var i=0; i<step; i++) {
        for (var j=0; j<stop && copyDeck.length>0; j++) {
            newDeck[i + (j*step)] = copyDeck.shift();
        }        
    }
    return newDeck;
}

答案 1 :(得分:1)

由于我被迫尽早添加自己的答案(修改以修复RobG指出的错误):

function interleave(items,parts){
  var stride = Math.ceil( items.length / parts ) || 1;
  var result = [], len=items.length;
  for (var i=0;i<stride;++i){
    for (var j=i;j<len;j+=stride){
      result.push(items[j]);
    }
  }
  return result;
}

答案 2 :(得分:1)

没有for循环(我为相等的块添加了一些检查):

function interleave(arr, blocks)
{
    var len = arr.length / blocks, ret = [], i = 0;
    if (len % 1 != 0) return false;
    while(arr.length>0)
    {
       ret.push(arr.splice(i, 1)[0]);
       i += (len-1);
       if (i>arr.length-1) {i = 0; len--;}    
    }
    return ret;
}
alert(interleave([1,2,3,4,5,6,7,8], 2));

和操场:) http://jsfiddle.net/7tC9F/

答案 3 :(得分:1)

如何使用递归功能:

function interleave(a, n) {

  function f(a1, d) {

    var next = a1.length && f(a1.slice(d), d);
    a1.length = Math.min(a1.length, d);

    return function(a2) {
      if (!a1.length) {
        return false;
      }

      a2.push(a1.shift());
      if (next) {
        next(a2);
      }
      return true;
    };
  }

  var r = [], x = f(a, Math.ceil(a.length / n));
  while (x(r)) {}

  return r;
}

答案 4 :(得分:1)

Phrogz非常接近,但没有正确交错。这是基于这一努力:

function interleave(items, parts) {
   var len = items.length;
   var step = len/parts | 0;
   var result = [];

   for (var i=0, j; i<step; ++i) {
     j = i

     while (j < len) {
       result.push(items[j]);
       j += step;
     }
   }
   return result;
}

interleave([0,1,2,3], 2); // 0,2,1,3
interleave([0,1,2,3,4,5,6,7,8,9,10,11], 2) // 0,6,1,7,2,8,3,9,4,10,5,11
interleave([0,1,2,3,4,5,6,7,8,9,10,11], 3) // 0,4,8,1,5,9,2,6,10,3,7,11
interleave([0,1,2,3,4,5,6,7,8,9,10,11], 4) // 0,3,6,9,1,4,7,10,2,5,8,11
interleave([0,1,2,3,4,5,6,7,8,9,10,11], 5) // 0,2,4,6,8,10,1,3,5,7,9,11

答案 5 :(得分:1)

我可以获奖吗? :-D

function interleave(a, n) {
  var i, d = a.length + 1, r = [];

  for (i = 0; i < a.length; i++) {
    r[i] = a[Math.floor(i * d / n % a.length)];
  }

  return r;
}

根据我的测试r.push(...r[i] = ...更快,所以你可以这样做..

请注意,这仅适用于完全可被n整除的集合,这是我能提出的最优化版本:

function interleave(a, n) {
  var i, d = (a.length + 1) / n, r = [a[0]];

  for (i = 1; i < a.length; i++) {
    r.push(a[Math.floor(i * d) % a.length]);
  }

  return r;
}

O(n-1),任何人都可以提出日志版本吗?到数学移动! [旋转数学家标志]

答案 6 :(得分:0)

试试这个:

function interleave(deck, base){
        var subdecks = [];
        for(count = 0; count < base; count++){
                subdecks[count] = [];
        }
        for(var count = 0, subdeck = 0; count < deck.length; count++){
                subdecks[subdeck].push(deck[count]);
                subdeck = subdeck == base - 1? 0 : subdeck + 1;
        }
        var newDeck = [];
        for(count = 0; count < base; count++){
                newDeck = newDeck.concat(subdecks[count]);
        }
        return newDeck;
}