如何用另一个数组的元素替换数组中的元素

50

我希望能够从某个数组的第 0 个元素开始,使用另一个长度可变的数组中的元素进行替换。例如:

var arr = new Array(10), anotherArr = [1, 2, 3], result;
result = anotherArr.concat(arr);
result.splice(10, anotherArr.length);

有更好的方法吗?


@NagaJolokia,[1,2,3,未定义,未定义...] - Artem Svirskyi
长度为10,对吗? - 1983
arr是否总是为空的,还是有时可能会有内容? - 1983
在我的情况下始终为空。 - Artem Svirskyi
7个回答

64
你可以使用 splice 方法从另一个数组中替换部分数组项,但你需要以特定的方式调用它,因为该方法期望作为参数的是数组项,而不是数组本身。 splice 方法期望的参数是这样的:(0, anotherArr.Length, 1, 2, 3),所以你需要创建一个包含这些参数的数组,并使用 apply 方法将这个数组作为参数来调用 splice 方法:
Array.prototype.splice.apply(arr, [0, anotherArr.length].concat(anotherArr));

例子:

var arr = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
var anotherArr = [ 1, 2, 3 ];

Array.prototype.splice.apply(arr, [0, anotherArr.length].concat(anotherArr));

console.log(arr);

输出:

[ 1, 2, 3, 'd', 'e', 'f', 'g', 'h', 'i', 'j']

演示: http://jsfiddle.net/Guffa/bB7Ey/

4
如果第一个数组比替换数组更长,上述解决方案将无法删除末尾的额外元素。进行轻微修改即可解决这个问题: Array.prototype.splice.apply(arr, [0, arr.length].concat(anotherArr)); - Loren_
@perilandmishap:是的,这就是重点。如果你想要替换数组,只需替换整个对象:arr = anotherArr; - Guffa
1
在Flux/Redux风格的状态管理器中,你经常使用const并且不允许更改对象的引用,因此仅进行重新赋值不是一个选项。这是一个愚蠢的问题,但JavaScript的状态目前有点愚蠢。 - Loren_

59

在ES6中,使用单个操作,您可以执行以下操作,将b的元素替换为a的前b.length个元素:

let a = [1,  2,  3,  4,  5]
let b = [10, 20, 30]

a.splice(0, b.length, ...b)

console.log(a) // -> [10, 20, 30, 4, 5]

可以使用 a.length(或者 Infinity)作为splice方法的长度参数,从而将整个数组内容替换掉。

let a = [1,  2,  3,  4,  5]
let b = [10, 20, 30]

a.splice(0, a.length, ...b)
// or
// a.splice(0, Infinity, ...b)

console.log(a) // -> [10, 20, 30], which is the content of b

a 数组的内容将被 b 完全替换。

注1:在我看来,仅应在性能关键的应用程序(例如高 FPS 动画)中使用数组突变,以避免创建新数组。通常,我会创建一个新数组来保持不可变性。

注2:如果 b 是一个非常大的数组,则不建议使用此方法,因为 ...b 被“展开”到 splice 的参数中,而 JS 函数可以接受的参数数量有限。在这种情况下,我建议使用另一种方法(或者尽可能创建一个新数组!)。


不错的解决方案!这比涉及 length 的解决方案更好,因为我还可以在同一个数组上进行映射。例如:let a = [5, 6, 7, 8]; a.splice(0, a.length, ...a.map(x => x * x)); 而且它也不需要重新分配给 a - nils
4
只需使用 a.splice(0, Infinity, ...b)。第二个参数无关紧要,只要它比要删除的元素数量大即可。 - GOTO 0
2
不错,但最初的问题是如何替换第一个数组的一部分。应该是 a.splice(0, b.length, ...b) - 使用 b 的长度进行测量。这样可以正确处理两个数组的任意长度。 - Sergey Nudnov
1
对于大型数组来说,这个速度非常慢,并且可能会导致“超出最大递归深度”的错误。 - WestCoastProjects
1
@javadba没错,对于非常大的数组,我认为你应该创建一个新的数组。我相信循环时间会克服创建时间。(无论如何,“最大递归”错误相当神秘...在那段代码中没有递归,而且我认为浏览器实现中从来没有递归) - caesarsol
1
@javadba 我添加了注释2以发出警告!谢谢。 - caesarsol

13

在 ES6、TypeScript、Babel 或类似工具中,您可以这样做:

arr1.length = 0; // Clear your array
arr1.push(...arr2); // Push the second array using the spread opperator

简单。


1
简单,但如果它是一个关联数组呢? - Tim Bogdanov
@TimBogdanov JS没有关联数组,你可能在想用作“数组”的“对象”(而“数组”是一个“对象”,可以在这个角色中扮演双重角色,但这是不正规和不建议的),或者使用较新的“Map”对象。 - ken

7

对于任何想要用另一个数组的完整内容替换一个数组的整个内容并保留原始数组的人:

Array.prototype.replaceContents = function (array2) {
    //make a clone of the 2nd array to avoid any referential weirdness
    var newContent = array2.slice(0);
    //empty the array
    this.length = 0;
    //push in the 2nd array
    this.push.apply(this, newContent);
};

原型函数将数组作为参数,用它作为新的数组内容进行克隆以避免任何奇怪的引用问题,清空原始数组,然后将传入的数组作为内容推入其中。这样可以保留原始数组和任何引用。

现在你只需要这样做:

var arr1 = [1, 2, 3];
var arr2 = [3, 4, 5];
arr1.replaceContents(arr2);

我知道这并不严格符合最初的问题,但当你在谷歌中搜索时,这个问题会首先出现,并且我想其他人可能会发现这对他们有用,因为这是我所需要的答案。


3
您可以使用splice方法,在删除旧元素的同时添加新元素:
您可以使用splice方法,在删除旧元素的同时添加新元素: splice
var arr = new Array(10), anotherArr = [1, 2, 3];

arr.splice.apply(arr, [0, anotherArr.length].concat(anotherArr))

如果您不想修改 arr 数组,您可以使用返回数组的浅拷贝的 slice 方法:

var arr = new Array(10), anotherArr = [1, 2, 3], result = arr.slice(0);

result.splice.apply(result, [0, anotherArr.length].concat(anotherArr));

或者,你可以使用 slice 来截取前面的元素,并在顶部添加 anotherArr

result = anotherArr.concat(arr.slice(anotherArr.length));

1
我不确定这是否是一种“更好”的方法,但至少它允许您选择起始索引(而您的解决方案仅从索引0开始起作用)。这里有一个示例。
// Clone the original array
var result = arr.slice(0);
// If original array is no longer needed, you can do with:
// var result = arr;

// Remove (anotherArr.length) elements starting from index 0
// and insert the elements from anotherArr into it
Array.prototype.splice.apply(result, [0, anotherArr.length].concat(anotherArr));

(该死,这么多忍者。:-P)


1
在这种情况下,您只需设置数组的长度。对于更复杂的情况,请参见@Guffa的答案。
var a = [1,2,3];
a.length = 10;
a; // [1, 2, 3, undefined x 7]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接