2

For example, I want to write something like:

const initial = [1, 2, 3, 4];
const indexIWantToChange = 2;

const obj = {
  prop: () => {
    const newArr = [...initial];
    newArr[indexIWantToChange] = 'Something new';
    return newArr;
  }()
};

How to change one specific element in array by index without mutating the original array in a functional style? Is there a one-liner of this maybe?

Revels
  • 223
  • 1
  • 12
  • The array isn't immutable. What immutability are you referring to? –  Jul 31 '16 at 12:25
  • ...well anyway: `newArr = [...initial.slice(0, idx), 'Something new', ...initial.slice(idx+1)]` Maybe that's what you're after. I can't really tell what you want. –  Jul 31 '16 at 12:30
  • In languages that aren't inherently functional, trying to force a functional style without the use of a exhaustive library will just be inefficient. – Carcigenicate Jul 31 '16 at 12:31
  • @revels, take a look at https://facebook.github.io/immutable-js/ – Thomas Jul 31 '16 at 12:42

3 Answers3

4

Object.assign might be useful:

Object.assign([], initial, { [indexIWantToChange]: 'Something new' })

Snippet:

const initial = [1, 2, 3, 4];
const indexIWantToChange = 2;

let prop = Object.assign([], initial, { [indexIWantToChange]: 'Something new' });

console.log(prop);
trincot
  • 317,000
  • 35
  • 244
  • 286
2

most things functional that return an array are often done by map

const initial = [1, 2, 3, 4];
const indexIWantToChange = 2;
const newValue = "blah"

let changed = initial.map((x,i) => i == indexIWantToChange ? newValue : x )
Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156
  • Yeah that's the one way of doing it, but it goes through a whole array. Maybe some helper function? I haven't find any of this kind in lodash docs. – Revels Jul 31 '16 at 12:24
  • 1
    @Revels, if with *save immutability* you mean *without mutating the original array*, then you must iterate through the array, which is what the spread operator in your original code does as well. How would you imagine to get a variant of the array without going *through a whole array*? – trincot Jul 31 '16 at 12:29
0

There are tons of way to do this in a so called functional way. @Keith Nicholas has a nice solution. Since you need a clone array, O(n) time complexity is essential.

Another way would be

var        initial = [1, 2, 3, 4],
indexIWantToChange = 2,
          newValue = "whatever",
           changed = initial.reduce((p,c,i) => i === indexIWantToChange ? p.concat(newValue) : p.concat(c),[]);
console.log(changed);
Redu
  • 25,060
  • 6
  • 56
  • 76