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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:02:21  来源:igfitidea点击:

Replace element at specific position in an array without mutating it

javascriptarraysecmascript-6immutability

提问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, arrayvariable 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.jsMori 之类的库的不可变变体。

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)

请参阅JSPerf(感谢@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 mapdoesn'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]