Modify an array without mutation

Viewed 10252

I am trying to solve a problem which states to remove(delete) the smallest number in an array without the order of the elements to the left of the smallest element getting changed . My code is -:

function removeSmallest(numbers){
    var x =  Math.min.apply(null,numbers);
    var y = numbers.indexOf(x);
    numbers.splice(y,1);
    return numbers;
}

It is strictly given in the instructions not to mutate the original array/list. But I am getting an error stating that you have mutated original array/list . How do I remove the error?

6 Answers

Listen Do not use SPLICE here. There is great known mistake rookies and expert do when they use splice and slice interchangeably without keeping the effects in mind.

SPLICE will mutate original array while SLICE will shallow copy the original array and return the portion of array upon given conditions.

Here Slice will create a new array

const slicedArray = numbers.slice()
const result = slicedArray.splice(y,1);

and You get the result without mutating original array.

first create a copy of the array using slice, then splice that

function removeSmallest(numbers){
    var x =  Math.min.apply(null,numbers);
    var y = numbers.indexOf(x);
    return numbers.slice().splice(y,1);
}

You can create a shallow copy of the array to avoid mutation.

function removeSmallest(numbers){
    const newNumbers = [...numbers];

    var x =  Math.min.apply(null,newNumbers);
    var y = newNumbers.indexOf(x);
    newNumbers.splice(y,1);

    return newNumbers;
}

array.slice() and [... array] will make a shallow copy of your array object.

"shallow" the word says itself. in my opinion, for copying your array object the solution is:

var array_copy = copy(array);

// copy function
function copy(object) {
    var output, value, key;
    output = Array.isArray(object) ? [] : {};
    for (key in object) {
        value = object[key];
        output[key] = (typeof value === "object") ? copy(value) : value;
    }
    return output;
}

Update

Alternative solution is:-

var arr_copy = JSON.parse(JSON.stringify(arr));

Let's focus on how to avoid mutating(I hope you don't mean "remove an error" as "supress error message"or something like that)

There are different methods on Array.prototype and most don't mutate array but return new array as a result. say .map, .slice, .filter, .reduce

Telling the truth just few mutates(like .splice)

So depending on what're additional requirements you may find say .map useful

 let newArray = oldArray.filter(el => el !== minimalElementValue);

or .map

 let newArray = oldArray.map(el => el === minimalElementValue? undefined: el);

For sure, they are not equal but both don't mutate original variable

I'm not sure what the exact context of the problem is, but the goal might be to learn to write pure transformations of data, rather than to learn how to copy arrays. If this is the case, using splice after making a throwaway copy of the array might not cut it.

An approach that mutates neither the original array nor a copy of it might look like this: determine the index of the minimum element of an array, then return the concatenation of the two sublists to the right and left of that point:

const minIndex = arr =>
  arr.reduce(
    (p, c, i) => (p === undefined ? i : c < arr[p] ? i : p),
    undefined
  );
const removeMin = arr => {
  const i = minIndex(arr);
  return minIndex === undefined
    ? arr
    : [...arr.slice(0, i), ...arr.slice(i + 1)];
};

console.log(removeMin([1, 5, 6, 0, 11]));

Related