JavaScript在循环中改变数组

时间:2015-03-26 11:43:16

标签: javascript arrays in-place

我想使用JavaScript复制数组中的某些数组,例如:

var res = [["1,2,3",100,50],["4,5",75,10],["6",20,90]];
var res2 = [];
for(var z in res) {
  var row = res[z];
  var keys = row[0].split(',')
  for(var y in keys) {
    var key = keys[y];
    res2.push([key,row[1]/keys.length,row[2]/keys.length]);
  }
}
/* 
[ [ '1', 33.333333333333336, 16.666666666666668 ],
  [ '2', 33.333333333333336, 16.666666666666668 ],
  [ '3', 33.333333333333336, 16.666666666666668 ],
  [ '4', 37.5, 5 ],
  [ '5', 37.5, 5 ],
  [ '6', 20, 90 ] ]
*/

数组真的非常长,是否可以就地执行此操作(res,而不是res2)?

3 个答案:

答案 0 :(得分:6)

您可以使用splice进行res的真实就地处理:

for (var i = 0; i < res.length; ) {
  var row = res[i];
  var keys = row[0].split(',')
  res.splice(i, 1); // Remove old element
  // Insert new elements at current position
  for (var j in keys)
    res.splice(i++, 0, [keys[j], row[1] / keys.length, row[2] / keys.length]);
}

结果:

[
 ["1", 33.333333333333336, 16.666666666666668],
 ["2", 33.333333333333336, 16.666666666666668],
 ["3", 33.333333333333336, 16.666666666666668],
 ["4", 37.5, 5],
 ["5", 37.5, 5],
 ["6", 20, 90]
]

修改

避免拼接的另一个技巧是扩展res的大小并开始从结尾填充它:

var n = res.length;

// Precalculate new length
var length = 0;
for (var i = 0; i < res.length; i++)
    length += res[i][0].split(',').length;

// Change length of array
res.length = length;

// Start filling from end to start
for (var i = n - 1, k = length - 1; i >= 0; i--) {
    var row = res[i];
    var keys = row[0].split(',');
    for (var j = keys.length - 1; j >= 0; j--)
        res[k--] = [keys[j], row[1] / keys.length, row[2] / keys.length];
}

答案 1 :(得分:2)

您可以使用Array.reduce

获取它
var res = [["1,2,3",100,50],["4,5",75,10],["6",20,90]];
res = res.reduce(function(a, b){
   var parts = b[0].split(',');
   parts.forEach(function(i){
     a.push([i, b[1]/parts.length, b[2]/parts.length]);
   });
   return a;
}, []);

但是,我相信这仍然会吃掉双重记忆:)

另一种解决方案(res2,但更经济):
它逐个获取源实体,处理它并允许gc清理内存......

var res2 = [];
while (res.length) {
    var cur = res.shift();
    var ids = cur[0].split(',')
    ids.forEach(function(i){
      res2.push(i, cur[1]/ids.length, cur[2]/ids.length);
    });
}

答案 2 :(得分:2)

您可以使用reduce这样的功能

var res = [["1,2,3",100,50],["4,5",75,10],["6",20,90]];
var r = res.reduce(function(acc,curr){
            return acc.concat(curr[0].split(',').map(function(el,_,cursplit){
                return [el, curr[1]/cursplit.length,curr[2]/cursplit.length];
            }));
        },[]);

但我不确定它更具可读性

&#13;
&#13;
var res = [["1,2,3",100,50],["4,5",75,10],["6",20,90]];
    var r = res.reduce(function(acc,curr){
        return acc.concat(curr[0].split(',').map(function(el,_,cursplit){
            return [el, curr[1]/cursplit.length,curr[2]/cursplit.length];
        }));
    },[]);

document.getElementById('d').innerHTML = r.join('<br>');
&#13;
<div id="d"></div>
&#13;
&#13;
&#13;

<强>更新 mutate res

的另一个变种
for(var i=0,len=res.length;i<len;i++){
    var cur = res.shift();
    cur[0].split(',').forEach(function(el,_,cursplit){
            res.push([el, cur[1]/cursplit.length,cur[2]/cursplit.length]);
    });
}

&#13;
&#13;
var res = [["1,2,3",100,50],["4,5",75,10],["6",20,90]];
for(var i=0,len=res.length;i<len;i++){
    var cur = res.shift();
    cur[0].split(',').forEach(function(el,_,cursplit){
            res.push([el, cur[1]/cursplit.length,cur[2]/cursplit.length]);
    });
}

document.getElementById('d').innerHTML = res.join('<br>');
&#13;
<div id="d"></div>
&#13;
&#13;
&#13;