Почему этот цикл for не возвращает предполагаемый результат?

Это просто упражнение в курсе, это приложение выбирает случайный фрукт из массива фруктов, а затем функция removeItem() должна удалить его из массива и вернуть измененный массив, но я получаю странный вывод, и функция не работает.

Проблема видна здесь

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.info({fruitArray, fruitItem, remaining});

Пожалуйста, разместите вывод здесь в виде текста, а не ссылок на изображения, чтобы нам было легче понять, что «не так».

deceze 16.05.2022 16:43

извините, я изменил это ?

ilgar 16.05.2022 16:50

Вы должны объяснить по-английски, в чем заключается проблема: «Когда срывают вишню, кажется, что арбуз также удаляется из списка». Постарайтесь свести к минимуму работу, которую должны будут выполнить другие, просматривая ваш вопрос.

Juan Mendes 16.05.2022 16:58

Спасибо за совет, я учусь и учту это, когда буду задавать вопросы в будущем?

ilgar 16.05.2022 17:10

Обратите внимание, что ваш вопрос не имеет ничего общего с React. Я добавил живой пример, который вы можете использовать, демонстрирующий ваш неработающий код. Вы всегда должны удалять любой код, который не связан с проблемой

Juan Mendes 16.05.2022 17:21

Пожалуйста, попробуйте написать заголовок, который поможет отличить ваш вопрос от других подобных вопросов на этом сайте.

Wyck 16.05.2022 17:44
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
6
73
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

В функции removeItem есть две проблемы:

  1. Если случайный элемент не является первым элементом в массиве, функция возвращает not found. Он вообще не будет работать для второго цикла, так как ваша функция возвращает not found после первой итерации.

  2. Метод splice обновляет исходный массив. Пока вы передаете fruitArray методу removeItem, он передается как ссылка, и его обновление внутри функции с использованием splice также обновит фактический массив.

Самый простой и безопасный способ удаления элемента из массива -

function removeItem(importedArray, item) {
  const filteredArray = importedArray.filter((each) => each !== item);
  if (filteredArray.length === 0) return 'Not Found';
  return filteredArray;
}

Возникнет проблема, если есть два элемента одного типа (значения).

Ron Hillel 16.05.2022 17:00

Почему вы предлагаете не использовать сплайсинг? Использование фильтра для удаления элемента может привести к сканированию всего массива, даже если он находит совпадение в первом элементе. Нет необходимости в тесте include, не так ли? Есть много ненужной работы.

Juan Mendes 16.05.2022 17:01

@RonHillel Судя по вопросу и коду ОП, не похоже, что будет два элемента одного типа.

Juan Mendes 16.05.2022 17:02

@JuanMendes ты прав. Это было не самое эффективное решение. Я обновил его. Это, скорее всего, решит проблемы, которые вы упомянули.

himayan 16.05.2022 17:12

@himayan Он все еще страдает от проблемы, которую вы на самом деле упомянули ? Вы изменяете массив, который вы использовали для отображения полного списка, вы можете создать новый массив, распространяя массив, как вы предлагали ранее. Я просто сказал, что вы не объяснили, почему они не должны изменять массив на месте (из-за ошибки, которую я только что упомянул)

Juan Mendes 16.05.2022 17:14

@JuanMendes Я тоже запутался. filter кажется лучшим способом сделать это. includes был ненужным.

himayan 16.05.2022 17:22

Как сказал химайан, проблема заключалась в том, что сращивание уже изменяет массив.

Вот мое решение:

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

  return importedArray;
}

Но если вы измените массив, то отображение существующего массива будет нарушено...

Juan Mendes 16.05.2022 17:03

Это в области функции, а не в области приложения. После этого функции не требуется запись исходного массива.

Ron Hillel 16.05.2022 17:03

Ему это нужно, он также отображает исходный массив. Я сделал ваш код работоспособным, чтобы вы могли увидеть, как он не работает.

Juan Mendes 16.05.2022 17:27

:) Это работает. Он не отображает массив в области функции removeItem...

Ron Hillel 16.05.2022 17:36

@RonHillel importedArray — это ссылка на исходный массив; это изменяет исходный массив. Вот почему ОП распространялся на новый массив.

Dave Newton 16.05.2022 17:37

Вы запутались, не имеет значения, локальная переменная или глобальная. И глобальные, и локальные переменные могут указывать на один и тот же массив.

Juan Mendes 16.05.2022 19:10

Ваша функция удаления элемента работает неправильно. Вместо того, чтобы писать циклы и объединять массив для создания нового, вы должны просто использовать метод filter

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

да, немного медленно, так как нет необходимости сканировать весь массив, но работает

Juan Mendes 16.05.2022 17:22

@JuanMendes Не могли бы вы объяснить, почему это решение работает медленнее?

ilgar 16.05.2022 18:24

Я думаю, это потому, что я сканирую весь массив, который имеет сложность n. Там может быть лучший способ сделать это.

Hammad Ali 16.05.2022 18:28

Да, потому что, если вы используете обычный цикл for, вы можете выйти из цикла, как только найдете свой элемент, тогда как filter будет продолжать перебирать весь массив.

Juan Mendes 16.05.2022 18:37
Ответ принят как подходящий

Было две основные проблемы:

  • Ваш цикл for в removeItem всегда возвращался на первой итерации.
  • Вы изменяли исходный массив, удаляя из него элементы

Я также удалил весь ненужный код, используемый для воспроизведения вашей проблемы. Прочтите Как спросить, чтобы убедиться, что вы помогаете другим помогать вам.

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.info({fruitArray, fruitItem, remaining});

Другие вопросы по теме