SEVENELEVEN
SEVENELEVEN

Reputation: 258

Why this rest parameter is usefull here?

I have two solutions for the same problem (both work), one is mine and the other one is from the internet.

My solution:

const removeFromArray = function(arr, ...Args) {

  for (i = 0; i <= Args.length; ++i) {
    if (arr.includes(Args[i])) {
      arr.splice(arr.indexOf(Args[i]), 1)
    }
  }

  return arr;
}

module.exports = removeFromArray

Internet's solution:

const removeFromArray = function(arr, ...Args) {

  let modifiedArray = [...arr]

  for (i = 0; i < arr.length; ++i) {
    if (modifiedArray.includes(Args[i])) {
      modifiedArray.splice(modifiedArray.indexOf(Args[i]), 1)
    }
  }

  return modifiedArray;
}

module.exports = removeFromArray

Test for both answers:

const removeFromArray = require('./removeFromArray')

describe('removeFromArray', function() {
  it('removes a single value', function() {
    expect(removeFromArray([1, 2, 3, 4], 3)).toEqual([1, 2, 4]);
  });
  it('removes multiple values', function() {
    expect(removeFromArray([1, 2, 3, 4], 3, 2)).toEqual([1, 4]);
  });
  it('ignores non present values', function() {
    expect(removeFromArray([1, 2, 3, 4], 7, "tacos")).toEqual([1, 2, 3, 4]);
  });
  it('ignores non present values, but still works', function() {
    expect(removeFromArray([1, 2, 3, 4], 7, 2)).toEqual([1, 3, 4]);
  });
  it('can remove all values', function() {
    expect(removeFromArray([1, 2, 3, 4], 1, 2, 3, 4, 5)).toEqual([]);
  });
  it('works with strings', function() {
    expect(removeFromArray(["hey", 2, 3, "ho"], "hey", 3)).toEqual([2, "ho"]);
  });
  it('only removes same type', function() {
    expect(removeFromArray([1, 2, 3], "1", 3)).toEqual([1, 2]);
  });
});

Upvotes: 2

Views: 42

Answers (2)

Friedrich Siever
Friedrich Siever

Reputation: 479

The second solution is nearer to functional programming pattern (pure function).

In functional programming you dont push or delete items into existing arrays or objects. You would rather create a new array with all the same items as the original array, Then you modify the duplicate and return it. The duplication is done by

let modifiedArray = [...arr]

The concept is described as pure Function. A function should not change anything outside the function. No side effects.

Upvotes: 0

Ivar
Ivar

Reputation: 6858

The difference between your code and the other one, is that yours changes the arr parameter directly whereas the other first makes a copy of the array, and then modifies that copy.

When you pass an array to a function, you are actually passing a reference to that array, not a copy of it. This means that when you modify arr directly, you are also modifying the source array.

Here is a nice example:

const removeFromArray1 = function(arr, ...Args) {

  for (i = 0; i <= Args.length; ++i) {

    if (arr.includes(Args[i])) {
      arr.splice(arr.indexOf(Args[i]), 1)
    }
  }
  return arr;
}

const removeFromArray2 = function(arr, ...Args) {

  let modifiedArray = [...arr]

  for (i = 0; i < arr.length; ++i) {

    if (modifiedArray.includes(Args[i])) {
      modifiedArray.splice(modifiedArray.indexOf(Args[i]), 1)
    }
  }
  return modifiedArray;
}

const arr1 = [1, 2, 3, 4];
console.log('Returned array 1', removeFromArray1(arr1, 3));
console.log('Source array 1', arr1);

const arr2 = [1, 2, 3, 4];
console.log('Returned array 2', removeFromArray2(arr2, 3));
console.log('Source array 2', arr2);

Here you can see that arr1 is modified after calling removeFromArray1, but arr2 is not modified after calling removeFromArray2. Changing the source array might have odd side-effects if you try to use the initial array expecting it not to be changed.

let modifiedArray = [...arr] is a simple way to make a shallow copy of the array.

Upvotes: 1

Related Questions