以特定方式分组/压缩多维数组的更有效/更聪明的方法

时间:2017-04-26 01:22:54

标签: javascript arrays node.js performance multidimensional-array

我有一个多维数组,我不知道它的大小,我所知道的是每个孩子都有相同的长度和相同的结构。

我需要将第一个子节点的内部数组与其兄弟节点的内部数组连接起来,这样所有子节点相同的索引内部数组都在一个数组中。

(如果有人想更好地说出来,或者将标题改为我的客人)

示例:

let arrays = [

    //1
    [[1, 2], [3, 4], [5, 6]],

    //2
    [[10, 20], [30, 40], [50, 60]],

    //3
    [[100, 200], [300, 400], [500, 600]],

    //N
    [[10000, 20000], [30000, 40000], [50000, 60000]],

];

预期结果:

[
    [1, 2, 10, 20, 100, 200, 10000, 20000],
    [3, 4, 30, 40, 300, 400, 30000, 40000],
    [5, 6, 50, 60, 500, 600, 50000, 60000]
]

以下是我目前正在做的事情,这项工作正在发挥作用,但这有点过头了。

/**
*   Helper function
*   Will return all the values at ${index} of each array in ${arrays}
*   Example: index(1, [[1,2], [3,4]]); //[2, 4]
*/

function index(index, arrays){

    let results = [];

    for(let i = 0, len = arrays.length; i < len; i++)
        results.push(arrays[i][index]);

    return results;
}

let first = arrays.shift();    
let output = first.map((item, i) => item.concat( ...index(i, arrays) ))

我正在寻找一种更有效的方法,因为它在节点服务器中运行,也是一种更聪明的方式(不一定非常有效)。

注意:我正在使用节点v7.8.0,因此可以使用ES6。

更新

点差运算符明显慢于apply

所以我的代码以这种方式更快:

return first.map((item, i) => [].concat.apply(item, index(i, clone) ));

JSPERF:

我测试了jsperf中的所有答案,而@ibrahimMahrir方式显然是最快的。

/**
*   Will return all the values at ${index} of each array in ${arrays}
*   Example: index(1, [[1,2], [3,4]]); //[2, 4]
*/

function index(index, arrays){

    let results = [];

    for(let i = 0, len = arrays.length; i < len; i++)
        results.push(arrays[i][index]);

    return results;
}

let arrays = [

	//1
	[[1, 2], [3, 4], [5, 6]],

	//2
	[[10, 20], [30, 40], [50, 60]],

	//3
	[[100, 200], [300, 400], [500, 600]],

	//N
	[[10000, 20000], [30000, 40000], [50000, 60000]],

];

let first = arrays.shift();
let output = first.map((item, i) => item.concat( ...index(i, arrays) ));

console.log(output);

3 个答案:

答案 0 :(得分:2)

这是一个典型的映射减少工作。你可以这样做;

var arrs = [[[1, 2], [3, 4], [5, 6]], [[10, 20], [30, 40], [50, 60]], [[100, 200], [300, 400], [500, 600]], [[10000, 20000], [30000, 40000], [50000, 60000]]],
    res  = arrs.reduce((p,c) => p.map((s,i) => s.concat(c[i])));
console.log(res);

答案 1 :(得分:1)

使用reduce及其姐妹会牺牲性能。使用基本的for循环并不是最好的,但肯定会更快。

function group(arrays){

    let results = [],
        len = arrays.length;

    if(!len) return results; // if this line is not necessary then remove it

    let i, j, k,
        innerLen = arrays[0].length;

    for(j = 0; j < innerLen; j++) {
        let arr = [];
        for(i = 0; i < len; i++)
            for(k = 0; k < arrays[i][j].length; k++) // assuming the last level of arrays could be of different lengths
                arr.push(arrays[i][j][k]);
        results.push(arr);
    }

    return results;
}

let arrays = [[[1,2],[3,4],[5,6]],[[10,20],[30,40],[50,60]],[[100,200],[300,400],[500,600]],[[10000,20000],[30000,40000],[50000,60000]]];
console.log(group(arrays));

答案 2 :(得分:1)

以下是我尝试使用zipflatten实用程序方法分解操作的可读方法:

&#13;
&#13;
let arrays = [
    //1
    [[1, 2], [3, 4], [5, 6]],
    //2
    [[10, 20], [30, 40], [50, 60]],
    //3
    [[100, 200], [300, 400], [500, 600]],
    //N
    [[10000, 20000], [30000, 40000], [50000, 60000]],
]

// from http://stackoverflow.com/a/10284006/7256039
const zip = a => a[0].map((_,i) => a.map(e => e[i]))

const flatten = a => [].concat(...a)

let result = zip(arrays).map(flatten)

console.log(result)
&#13;
.as-console-wrapper { min-height: 100%; }
&#13;
&#13;
&#13;

这是我能提出的最快的内联/循环版本,同时仍然没有牺牲太多的可读性:

&#13;
&#13;
let arrays = [
    //1
    [[1, 2], [3, 4], [5, 6]],
    //2
    [[10, 20], [30, 40], [50, 60]],
    //3
    [[100, 200], [300, 400], [500, 600]],
    //N
    [[10000, 20000], [30000, 40000], [50000, 60000]],
]

function zipMapFlatten (a) {
  const result = [], rows = a.length, cols = a[0].length
  let i, j, e
  for (j = 0; j < cols; j++) {
    result.push(e = [])
    for (i = 0; i < rows; i++) e.push.apply(e, a[i][j])
  }
  return result
}

let result = zipMapFlatten(arrays)

console.log(result)
&#13;
.as-console-wrapper { min-height: 100%; }
&#13;
&#13;
&#13;