Javascript 替换数组中特定位置的元素而不对其进行变异
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38060705/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Replace element at specific position in an array without mutating it
提问by Bless
How can the following operation be done without mutating the array:
如何在不改变数组的情况下完成以下操作:
let array = ['item1'];
console.log(array); // ['item1']
array[2] = 'item2'; // array is mutated
console.log(array); // ['item1', undefined, 'item2']
In the above code, array
variable is mutated. How can I perform the same operation without mutating the array?
在上面的代码中,array
变量发生了变异。如何在不改变数组的情况下执行相同的操作?
回答by Oriol
You can use Object.assign
:
您可以使用Object.assign
:
Object.assign([], array, {2: newItem});
回答by Elod Szopos
You can simply set up a a new array as such:
您可以简单地设置一个新数组:
const newItemArray = array.slice();
And then set value for the index which you wish to have a value for.
然后为您希望为其设置值的索引设置值。
newItemArray[position] = newItem
and return that. The values under the indexes in-between will have undefined
.
并返回。中间索引下的值将具有undefined
.
Or the obviously alternative would be:
或者明显的替代方案是:
Object.assign([], array, {<position_here>: newItem});
回答by Dan Prince
Well, technically this wouldn't be replacingas there isn't an item at the index you're changing.
好吧,从技术上讲,这不会被替换,因为您要更改的索引中没有项目。
Look at how it's handled in Clojure—a language that's built around canonical implementations for immutable data structures.
看看它是如何在 Clojure 中处理的——Clojure 是一种围绕不可变数据结构的规范实现而构建的语言。
(assoc [1] 2 3)
;; IndexOutOfBoundsException
Not only does it fail, but it crashes too. These data structures are designed to be as robust as possible and when you come up against these kinds of errors, it's generally not because you've discovered an edge case, but more likely that you're using the wrong data structure.
它不仅会失败,而且还会崩溃。这些数据结构被设计得尽可能健壮,当你遇到这些类型的错误时,通常不是因为你发现了一个边缘情况,而是你使用了错误的数据结构。
If you are ending up with sparse arrays, then consider modelling them with objects or maps instead.
如果您最终得到的是稀疏数组,那么请考虑使用对象或映射对它们进行建模。
let items = { 0: 1 };
{ ...items, 2: 3 };
// => { 0: 1, 2: 3 }
let items = new Map([ [0, 1] ]);
items(2, 3);
// => Map {0 => 1, 2 => 3}
However, Map is a fundamentally mutable data structure, so you'd need to swap this out for an immutable variant with a library like Immutable.jsor Mori.
但是, Map 是一种基本可变的数据结构,因此您需要将其替换为具有Immutable.js或Mori 之类的库的不可变变体。
let items = Immutable.Map([ [0, 2] ]);
items.set(2, 3);
// => Immutable.Map {0 => 1, 2 => 3}
let items = mori.hashMap();
mori.assoc(items, 2, 3);
// => mori.hashMap {0 => 1, 2 => 3}
Of course, there might be a perfectly good reason for wanting to use JavaScript's arrays, so here's a solution for good measure.
当然,想要使用 JavaScript 的数组可能有一个很好的理由,所以这里有一个很好的解决方案。
function set(arr, index, val) {
if(index < arr.length) {
return [
...arr.slice(0, position),
val,
...arr.slice(position + 1)
];
} else {
return [
...arr,
...Array(index - arr.length),
val
];
}
}
回答by Yves M.
The fastway
该快速路
function replaceAt(array, index, value) {
const ret = array.slice(0);
ret[index] = value;
return ret;
}
See the JSPerf(thanks to @Bless)
Related posts:
相关文章:
回答by just-boris
Here is how I'd like to do it:
这是我想怎么做:
function update(array, newItem, atIndex) {
return array.map((item, index) => index === atIndex ? newItem : item);
}
Generally, Array-spread operation produces few temporary arrays for you, but map
doesn't, so it can be faster. You can also look at this discussionas a reference
通常,数组扩展操作为您生成很少的临时数组,但map
不会,因此它可以更快。你也可以看看这个讨论作为参考
回答by YSJ
var list1 = ['a','b','c'];
var list2 = list1.slice();
list2.splice(2, 0, "beta", "gamma");
console.log(list1);
console.log(list2);
Is this what you want?
这是你想要的吗?
回答by Saksham
Another way could be to use spread operator with slice as
另一种方法是将扩展运算符与切片一起使用
let newVal = 33, position = 3;
let arr = [1,2,3,4,5];
let newArr = [...arr.slice(0,position - 1), newVal, ...arr.slice(position)];
console.log(newArr); //logs [1, 2, 33, 4, 5]
console.log(arr); //logs [1, 2, 3, 4, 5]