6

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?

8
  • 1
    splice will mutate an array, I think this is why your solution is being rejected. In order to avoid mutating the original array, you need to express the solution as building up a new array from the original one, sans smallest element. Commented Aug 24, 2018 at 20:52
  • How do you remove a number without mutating the list? The requirement doesn't make sense to me. Commented Aug 24, 2018 at 20:53
  • Removing something will almost always change the position of everything that came after the removed element. Commented Aug 24, 2018 at 20:53
  • 1
    I have a feeling "position of the elements" might mean "order of the elements"? Commented Aug 24, 2018 at 20:54
  • Perhaps by "removal" it means to replace the number with something that isn't a number, e.g. null or NaN? This would retain the original order and positions of the remaining values. Commented Aug 24, 2018 at 20:55

8 Answers 8

6

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.

Sign up to request clarification or add additional context in comments.

2 Comments

While true, this doesn't answer the question.
I tried to explain it theoretically but I added the more explanation above in my answer.
3

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

Comments

2

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

1 Comment

While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.
2

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));

Comments

1

ECMAScript 2023 introduced a method for this purpose: Array#toSpliced, and so now you can do:

function removeSmallest(numbers){
    const least = Math.min(...numbers);
    const i = numbers.indexOf(least);
    return numbers.toSpliced(i, 1);
}


const arr = [5,6,3,8,0,4,9];
const res = removeSmallest(arr);
console.log("original: ", ...arr);
console.log("result:   ", ...res);

Comments

0

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

Comments

0

Let's focus on how to avoid mutating. (I hope when you say "remove an error" you don't mean "suppress the error message" or something like that)

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

Telling the truth just a few mutate (like .splice)

So depending on what your additional requirements are you may find, say .filter 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 the original variable

Comments

0

If Array#toSpliced is available you should probably use that. If not then this answer shows how to splice without mutating the original array:

const arr1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
const arr2 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

const idx = 2
const len = 4

arr1.splice(idx, len)

const spliceSafe = (arr, idx, len) => {
  const a = arr.slice(0, idx)
  const b = arr.slice(idx + len)
  return [...a, ...b]
}

const spliceResult = arr1
const spliceSafeResult = spliceSafe(arr2, idx, len)

result = {
  splice: spliceResult,
  spliceSafe: spliceSafeResult,
  isEqual: _.isEqual(spliceResult, spliceSafeResult)
}

console.log(result)
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js" integrity="sha256-qXBd/EfAdjOA2FGrGAG+b3YBn2tn5A6bhz+LSgYD96k=" crossorigin="anonymous"></script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.