1

This is just an exercise in a course, this app selects a random fruit from the fruits array and then the removeItem() function is supposed to remove that one from the array and returns the modified array, but I'm getting a weird output, and the function is not working.

The problem can be seen here

function randomFruit(importedArray) {
  let random = Math.floor(Math.random() * importedArray.length);
  return importedArray[random];
}

function removeItem(importedArray, item) {
  for (let i = 0; i < importedArray.length; i++) {
    if (importedArray[i] === item) {
      importedArray.splice(i, 1);
      return [...importedArray.slice(0, i), ...importedArray.slice(i + 1)];
    } else {
      return "not found";
    }
  }
}

function makeFruitArray() {
  var foods = ["🍒", "🍉", "🍑", "🍐", "🍏"];
  return foods;
}

let fruitArray = makeFruitArray();
let fruitItem = randomFruit(fruitArray);
let remaining = removeItem(fruitArray, fruitItem);

console.log({fruitArray, fruitItem, remaining});

6
  • 2
    Please post the output as text here instead of links to images, so it's easier for us to understand what's "wrong". Commented May 16, 2022 at 14:43
  • sorry I changed it 🙏 Commented May 16, 2022 at 14:50
  • 1
    You should explain in English what the actual problem is: "When a cherry is picked, it seems to also remove the watermelon from the list". Try to minimize the work others will have to do when scanning through your question. Commented May 16, 2022 at 14:58
  • Thanks you for the advice, I'm learning and will take that to account when asking questions in the future🙏 Commented May 16, 2022 at 15:10
  • Note that your question has nothing to do with React. I added a live example you can use that demonstrates your non-working code. You should always to remove any code that is not related to the problem Commented May 16, 2022 at 15:21

4 Answers 4

2

There are two issues in the removeItem function -

  1. If the random one is not the first item on the array, the function returns not found. It wouldn't run for the second loop at all, as your function returns not found after the first iteration.

  2. The splice method updates the original array. While you are passing the fruitArray to the removeItem method, it gets passed as reference and updating it within the function using splice will update the actual array as well.

The simplest and safest way of removing an item from an array would be -

function removeItem(importedArray, item) {
  const filteredArray = importedArray.filter((each) => each !== item);
  if (filteredArray.length === 0) return 'Not Found';
  return filteredArray;
}
Sign up to request clarification or add additional context in comments.

6 Comments

There will be an issue if there are two items of the same type (value).
Why are you suggesting that splice should not be used? Using filter to remove an element may cause it to scan the entire array even if it finds a match at the first element. No need for the includes test, is there? There's a lot of unnecessary work.
@RonHillel From the question and the OP's code, it doesn't look like there would be two items of the same type.
@JuanMendes you are right. It was not the most performant solution. I have updated it. This would most likely address the problems you mentioned.
@himayan It still suffers from the problem you actually mentioned 😜 You are modifying an array that you were using for displaying the full list, you can create a new array spreading the array as you suggested before. I was just saying that you weren't explaining why they shouldn't modify the array in place (because of the bug I just mentioned)
|
1

There were two major problems:

  • Your for loop in removeItem was always returning on the first iteration
  • You were modifying the initial array as you removed items from it

I've also removed all the unnecessary code used to reproduce your problem.

function randomFruit(importedArray) {
  let random = Math.floor(Math.random() * importedArray.length);
  return importedArray[random];
}

function removeItem(importedArray, item) {
  for (let i = 0; i < importedArray.length; i++) {
    if (importedArray[i] === item) {
      // Don't modify the original array since we want to
      // display the original fruits  
      return [...importedArray.slice(0, i), ...importedArray.slice(i + 1)];
    }
  }
  // Error condition goes outside the loop, not inside.
  return null;
}

function makeFruitArray() {
  var foods = ["🍒", "🍉", "🍑", "🍐", "🍏"];
  return foods;
}

let fruitArray = makeFruitArray();
let fruitItem = randomFruit(fruitArray);
let remaining = removeItem(fruitArray, fruitItem);

console.log({fruitArray, fruitItem, remaining});

Comments

1

Your remove item function is not working correctly. Instead of writing loops and splicing the array to create a new one you should just use the filter method

function removeItem(importedArray, item) {
    let newArray = importedArray.filter(function (element) {
        return element !== item;
    });
    return newArray;
}

4 Comments

yes, slightly slow since there's no need to scan the entire array, but it works
@JuanMendes Can you please explain why is this solution slower?
I think it's because I am scanning the entire array which has n complexity. There might be a better way to do it.
Yes, it's because if you use a regular for loop, you can exit the loop as soon as you find your item whereas filter will keep iterating over the entire array.
1

As himayan said, the issue was that splice already changes the array.

Here's my solution:

function removeItem(importedArray, item) {
  for (let i = 0; i < importedArray.length; i++) {
    if (importedArray[i] === item) {
      importedArray.splice(i, 1);
      break;
    }
  }

  return importedArray;
}

6 Comments

But if you modify the array, then the display the existing array will be broken...
It's in the function scope, not the app scope. The function doesn't need a record of the original array afterward.
It does need it, it displays the original array also. I've made your code runnable so you can see how it doesn't work.
:) It does work. It's not displaying the array in the removeItem function scope...
@RonHillel importedArray is a reference to the original array; this modifies the original array. That's why the OP was spreading into a new array.
|

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.