1

I'm using splice to remove the last n number of elements on an array (denoted by quizResponseCountToRemove).

However, in its currently implementation, it only removes 1 element.

Is there any particular reason for this?

My code is as follows;

  static removeCourseContentElementQuizResponseCount(
    course: ICourse,
    courseContents: ICourseContent[],
    selectedCourseContentUid: string,
    selectedCourseModule: number,
    quizResponseCountToRemove: number
  ): ICourse {
    courseContents.map((courseContent) => {
      if (courseContent.uid === selectedCourseContentUid) {
        courseContent.quiz.options.splice(-1, quizResponseCountToRemove);
        if (courseContent.quiz.answer > courseContent.quiz.options.length) {
          courseContent.quiz.answer = 1;
        }
      }
    });
    course.modules[selectedCourseModule].content = courseContents;
    return course;
  }

Update

It seems I have misunderstood how splice works. I want splice to work backwards from the last element. So in an array ['test1', 'test2', 'test3', 'test4'], if quizResponseCountToRemove is 2 then I end up with ['test1', 'test2'].

methuselah
  • 12,766
  • 47
  • 165
  • 315
  • 3
    Don't use `map` when you're not using the array it creates. Use `forEach` or [any of your other options for looping arrays](https://stackoverflow.com/questions/9329446/for-each-over-an-array-in-javascript). – T.J. Crowder Apr 17 '21 at 13:38

2 Answers2

3

If you pass splice a negative number for the first argument, that's an offset from the end of the array at which to perform the splice action. You're passing -1, so it'll perform its action on the last entry in the array. By definition, there's only one last entry in the array, so it doesn't matter how large quizResponseCountToRemove is. If it's any number over 0, only one element (the last one) will be removed.

In a comment you've said:

I want splice to work backwards from the last element. So in an array ['test1', 'test2', 'test3', 'test4'], if quizResponseCountToRemove is 2 then I end up with ['test1', 'test2']

In that case, you want to start quizResponseCountToRemove from the end, so you could pass in -quizResponseCountToRemove:

courseContent.quiz.options.splice(-quizResponseCountToRemove, quizResponseCountToRemove);

...but that's unnecessarily complicated. To truncate an array, you can just assign to its length:

courseContent.quiz.options.length -= quizResponseCountToRemove;

If it's possible that quizResponseCountToRemove might be larger than the array's length, you'll need to ensure you don't try to assign a negative number to length (which will cause an error):

courseContent.quiz.options.length = Math.max(0, courseContent.quiz.options.length - quizResponseCountToRemove);

Live Example:

const courseContent = {
    quiz: {
        options: ["test1", "test2", "test3", "test4"],
    },
};
const quizResponseCountToRemove = 2;
console.log("before", JSON.stringify(courseContent.quiz.options));
courseContent.quiz.options.length -= quizResponseCountToRemove;
console.log("after", JSON.stringify(courseContent.quiz.options));
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks for responding. It seems I misunderstood how splice works. I want splice to work backwards from the last element. So in an array `['test1', 'test2', 'test3', 'test4']`, if `quizResponseCountToRemove` is 2 then I end up with `['test1', 'test2']`. – methuselah Apr 17 '21 at 13:43
  • 1
    Thanks for the prompt reply TJ. Much appreciated! Will mark as correct shortly. – methuselah Apr 17 '21 at 13:45
  • `splice` doesn't seem to delete multiple items when start index is negative. `console.log(["test1", "test2", "test3", "test4"].splice(-1, 2))` This does not delete the last two items. Can you please tell why? – Som Shekhar Mukherjee Apr 17 '21 at 13:53
  • @SomShekharMukherjee - I explained why in the answer above. – T.J. Crowder Apr 17 '21 at 14:02
  • Ya got it! I got a little confused. – Som Shekhar Mukherjee Apr 17 '21 at 14:04
0

You can use slice if you are looking to truncate an array. The problem with setting length of the array is that the length should be non-negative, so you need to add some checks.

In code snippet below even if delCount is 200, no additional checks are required slice will simply return an empty array. But remember slice returns a new array.

const arr = ["test1", "test2", "test3", "test4"],
  delCount = 2,
  newArr = arr.slice(0, -delCount);

console.log(newArr)
Som Shekhar Mukherjee
  • 4,701
  • 1
  • 12
  • 28