交错排列阵列元素

Interleave array elements

本文关键字:元素 阵列 排列      更新时间:2023-09-26

什么是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整除时,我不太关心会发生什么。合理的答案可能会把剩下的东西交织在一起,甚至"踢"一下,把它们都扔到最后。

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;
}

它可以用计数器而不是移位()来完成

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;
}

我能获奖吗?:-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),有人能想出一个日志版本吗?去数学手机![旋转mathman徽标]

没有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/

函数与递归的关系如何:

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;
}

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

由于我被要求提前添加自己的答案(经过编辑以修复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;
}

试试这个:

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;
}