Replace element at specific position in an array without mutating it

前端 未结 7 614
感情败类
感情败类 2021-01-31 08:20

How can the following operation be done without mutating the array:

let array = [\'item1\'];
console.log(array); // [\'item1\']
array[2] = \'item2\'; // array is         


        
7条回答
  •  栀梦
    栀梦 (楼主)
    2021-01-31 09:02

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

提交回复
热议问题