Replace element at specific position in an array without mutating it

我的梦境 提交于 2020-12-27 08:12:46

问题


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?


回答1:


You can use Object.assign:

Object.assign([], array, {2: newItem});



回答2:


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.

Or the obviously alternative would be:

Object.assign([], array, {<position_here>: newItem});



回答3:


Well, technically this wouldn't be replacing as 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.

(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.js or 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.

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
    ];
  }
}



回答4:


The fast way

function replaceAt(array, index, value) {
  const ret = array.slice(0);
  ret[index] = value;
  return ret;
}

See the JSPerf (thanks to @Bless)

Related posts:

  • Javascript fastest way to duplicate an Array - slice vs for loop
  • https://github.com/lodash/lodash/issues/2053#issuecomment-188776090



回答5:


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 discussion as a reference




回答6:


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?




回答7:


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]


来源:https://stackoverflow.com/questions/38060705/replace-element-at-specific-position-in-an-array-without-mutating-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!