如何将元素推送到3D数组(Javascript)

时间:2017-06-22 15:12:33

标签: javascript typescript

我有一个对象

1:a
2:b
3:c
4:d
5:e
6:f
7:g
8:h
9:i

我想制作一个3D数组,比如

[
  [ [a], [b], [c] ],
  [ [d], [e], [f] ],
  [ [g], [h], [i] ]
] 

是否可以编写for-loop将前三个字母推送到3D数组,而不是后三个字母和第三个字母(如示例中所示)?

4 个答案:

答案 0 :(得分:2)

根据@Andreas评论 Does JavaScript Guarantee Object Property Order?

无法保证对象中的属性顺序。因此,如果您需要依赖keyVal命令,则必须在Object.keys上执行新步骤:sorting

解决方案可以基于Object.keys和模数运算符进行循环,以便按行或除以行排序:



var obj = {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i'};

var resultByCol = [];
var resultByRow = [];
var objKeys = Object.keys(obj).sort(function(a, b) {
    return a - b;
});
for (var idx = 0; idx < objKeys.length; idx++) {
    var newIdx = idx % 3;
    if (resultByCol[newIdx] === undefined) {
        resultByCol.push([]);
    }
    resultByCol[newIdx].push([obj[objKeys[idx]]]);



    newIdx = Math.floor(idx / 3);
    if (resultByRow[newIdx] === undefined) {
        resultByRow.push([]);
    }
    resultByRow[newIdx].push([obj[objKeys[idx]]]);
}


console.log('Grouped by Col: [');
for (var i = 0; i < resultByCol.length; i++) {
    console.log('\t' + JSON.stringify(resultByCol[i]) + (((i + 1) == resultByCol.length) ? '' : ','));
}
console.log(']');

console.log('Grouped by Row: [');
for (i = 0; i < resultByRow.length; i++) {
    console.log('\t' + JSON.stringify(resultByRow[i]) + (((i + 1) == resultByRow.length) ? '' : ','));
}
console.log(']');
&#13;
&#13;
&#13;

答案 1 :(得分:2)

您可以先对Object.keys()数组进行排序,然后使用reduce()按每3个键创建一个新数组。

var obj = {1: 'a',2: 'b',3: 'c',4: 'd',5: 'e',6: 'f',7: 'g',8: 'h',9: 'i',}

var result = Object.keys(obj).sort((a, b) => a - b).reduce(function(r, e, i) {
  if(i % 3 == 0) r.push([]);
  r[r.length - 1].push([obj[e]])
  return r;
}, [])

console.log(result)

答案 2 :(得分:1)

使用keys和简单的for循环可以非常快速有效地实现这一目标,以保证代码的便捷性。

@ gaetanoM的解决方案可以很好地工作,但是对于更高效的功能,您可以执行以下操作:

var object = {1:'a', 2:'b', 3:'c', 4:'d', 5:'e', 6:'f', 7:'g', 8:'h', 9:'i'};
var keys = Object.keys(object);
var result = [];
for ( var i=, j=keys.length; i<j; i++){
    result[i] = object[keys[i]];
}

答案 3 :(得分:1)

是。有很多方法可以做到这一点。可能最干净的是使用reduce()函数:

const obj = { 1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i' };

const width = 3; // how many in each sub array.
const result = Object.keys(obj).map(key => obj[key]) // ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
  .reduce((result, v) => {
    if (result[result.length - 1].length === width) {
      result.push([v]); // add new row
    } else {
      result[result.length - 1].push(v); // add to last row
    }
    return result;
  }, [[]]);
  
console.log(result);

这需要更加冗长,但更容易理解。

首先,我将对象循环到map()到正常数组。

然后,在reduce()函数中,我用第一级嵌套数组启动它。然后在每个循环中,我检查结果中最后一个数组的长度。如果它已满,我为下一行添加一个新数组。否则,我只是将值添加到最后一行。

更紧凑的版本是:

const obj = { 1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i' };
const width = 3;

const result = Object.keys(obj).reduce((r, k) => 
  r.concat(
    r[r.length - 1].length === width 
      ? [[obj[k]]]
      : [r.pop().concat(obj[k])]
  ), [[]]);

console.log(result);

这个例子更多地使用了.concat(),所以一切都在技术上在一条线上,但显然它更难以阅读和理解。