4

在循环时修改数组是否安全,例如推送元素?

我使用下划线每种方法

4

2 回答 2

2

我建议避免each,除非您绝对需要对集合中的每个项目产生副作用(触发事件、打印结果等)。对于简单地修改您的收藏,有更好的方法。

如果每个添加的元素只是单个输入元素的结果,则典型的功能模式将是flatmap数组,可以认为是两个步骤:

  1. 用于应用map一个函数,该函数为每个元素生成一个数组作为结果。总体结果将是一个数组数组。
  2. 使用flatten该数组数组来获得一维数组。

使用下划线lodash

var origArray = [1, 2, 3, 4];
var duplicateIf3 = function (val) { return val === 3 ? [val, val] : val; };
_.flatten(origArray.map(duplicateIf3));
// -> [1, 2, 3, 3, 4]

(在类型化的 FP 中,函数必须返回[val]不是 3 的值,但flatten不在乎——它会将你给它的任何内容展平为一维。)

如果新元素依赖于它之前的所有元素,您可能会使用reduceorfold代替,将空数组作为初始值。

var origArray = [1, 2, 3, 4];
origArray.reduce(function (acc, val) { return acc.concat(acc).concat(val); }, []);
// -> [1, 1, 2, 1, 1, 2, 3, 1, 1, 2, 1, 1, 2, 3, 4]

(对不起,我想不出一个现实的例子,但这里的每一步都以非常简单的方式使用所有先前步骤的完整输出来进行说明,你可以从原始数组的每个值中看到发生了什么。另请注意如果您不想使用下划线/lodash flatten,您可以自己制作 reduce

reduce比 更通用flatmap,但两种方法都能够将数组转换为更大的数组,这在某种程度上取决于第一个数组。

如果您有兴趣了解这方面的更多信息,我强烈建议您查看 Reg Braithwaite 的免费(在线)Javascript Allongé

于 2013-11-01T04:57:27.260 回答
1

我不确定您所说的安全是什么意思,但是您必须有充分的理由这样做。我玩了一下,这就是我得到的:

_.each(a, function(el) { 
    if (el % 2 == 0) 
        a.push(el + 1); 
    console.log(el); 
});

// logs 1, 2, 3, 4, 5

console.log(a);
// logs [ 1, 2, 3, 4, 5, 3, 5 ]

在这种情况下,除非您想查看添加的元素,否则不会产生负面影响,但是如果您要更改特定元素,您可能会发现自己处于更棘手的情况:

_.each(a, function(el, index) { 
    a[index + 1] = el - 1;
    if (el % 2 == 0) 
        a.push(el + 1); 
    console.log(el); 
});

// logs 1, 0, -1, -2, -3

_.map用于大多数用例会更有意义。

于 2013-11-01T04:46:10.487 回答