путаница в индексе метода соединения

#javascript #indexing #splice

Вопрос:

Я знаю, что это звучит забавно, так как я сам закодировал решение, но мне трудно понять, почему это работает после того, как я некоторое время его не видел. Алгоритм решает вопрос «Обновление инвентаря» от freecodecamp, хотя и с неудачным тестом (сравните и обновите инвентарь, хранящийся в 2D-массиве, со вторым 2D-массивом свежей доставки. Обновите текущие существующие количества товарно-материальных запасов (в arr1). Если товар не может быть найден, добавьте новый товар и количество в массив запасов. Возвращаемый массив инвентаря должен располагаться в алфавитном порядке по позициям.) Алгоритм выглядит следующим образом:

 function updateInventory(arr1, arr2) {  let newInv = [...arr1, ...arr2]  //create single list of items only from both arrays  let temp = newInv.flat().filter(item =gt; typeof item === 'string')  //create list of the index of all duplicate items  let duplicates = temp.reduce((acc, item, index) =gt; {  if (temp.indexOf(item) != index){  acc.push(index)  }  return acc  }, [])  //remove duplicate items  for (let index in duplicates) {  newInv.splice(index, 1)   }  //sort by alphabetical order  newInv.sort((a,b) =gt; {  return a[1] gt; b[1] ? 1 : -1  })  return newInv } // Example inventory lists var curInv = [  [21, "Bowling Ball"],  [2, "Dirty Sock"],  [1, "Hair Pin"],  [5, "Microphone"] ];  var newInv = [  [2, "Hair Pin"],  [3, "Half-Eaten Apple"],  [67, "Bowling Ball"],  [7, "Toothpaste"] ];  updateInventory(curInv, newInv);  

Насколько я понимаю, ожидаемый результат должен быть:

 [ [ 21, 'Bowling Ball' ],  [ 2, 'Dirty Sock' ],  [ 1, 'Hair Pin' ],  [ 3, 'Half-Eaten Apple' ],  [ 5, 'Microphone' ],  [ 7, 'Toothpaste' ] ]  

Однако, что такое получить, так это:

 [ [ 67, 'Bowling Ball' ],  [ 2, 'Dirty Sock' ],  [ 2, 'Hair Pin' ],  [ 3, 'Half-Eaten Apple' ],  [ 5, 'Microphone' ],  [ 7, 'Toothpaste' ] ]  

которые являются дублирующими парами элементов, которые он должен был удалить. Я уверен, что, возможно, мне не хватает чего-то простого, но я просто не понимаю этого.

Мы очень ценим вашу помощь

Комментарии:

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

Ответ №1:

Есть две проблемы. Первый — с циклом for

 let duplicates = [4, 6]   for (let index in duplicates) {  newInv.splice(index, 1)  }  

Ты делаешь «за«, а не «за«

в циклах по индексам (например, в индексе..!:)), для значений, превышающих значения
, если вы зарегистрируете индекс в цикле, вы увидите 0,1 = индексы элементов в дубликатах
, Измените его на для, тогда это 4,6 = значения элементов в дубликатах = индексы элементов, которые вы хотите удалить. Альтернативой было бы

 duplicates.forEach(i =gt; newInv.splice(i, 1))  

Проблема секунд заключается в том, что, когда вы удалили первый элемент, индекс второго элемента меняется 🙂 Так что теперь это не индекс 6, а 5. Это можно решить, изменив местами дубликаты перед циклированием и соединением, поэтому сначала начните с самого высокого индекса и удалите «от конца до начала».

Таким образом, это должно дать запрошенный результат

 function updateInventory(arr1, arr2) {  let newInv = [...arr1, ...arr2]  //create single list of items only from both arrays  let temp = newInv.flat().filter(item =gt; typeof item === 'string')  //create list of the index of all duplicate items  let duplicates = temp.reduce((acc, item, index) =gt; {  if (temp.indexOf(item) != index) {  acc.push(index)  }  return acc  }, []).reverse()  //remove duplicate items  for (let index of duplicates) {  newInv.splice(index, 1)  }  //sort by alphabetical order  newInv.sort((a, b) =gt; {  return a[1] gt; b[1] ? 1 : -1  })  return newInv  }   // Example inventory lists var curInv = [  [21, "Bowling Ball"],  [2, "Dirty Sock"],  [1, "Hair Pin"],  [5, "Microphone"] ];  var newInv = [  [2, "Hair Pin"],  [3, "Half-Eaten Apple"],  [67, "Bowling Ball"],  [7, "Toothpaste"] ];   let result = updateInventory(curInv, newInv);  console.log(result); 

И это был бы мой подход к решению задания

 function updateInventory(curInv, newInv) {  newInv.forEach(newItem =gt; {  let newItemName = newItem[1]   let inCurrent = curInv.find(currItem =gt; currItem[1] === newItemName)  if(!inCurrent) curInv.push(newItem)  })  return curInv.sort((a,b) =gt; a[1].localeCompare(b[1]))  }    // Example inventory lists var curInv = [  [21, "Bowling Ball"],  [2, "Dirty Sock"],  [1, "Hair Pin"],  [5, "Microphone"] ];  var newInv = [  [2, "Hair Pin"],  [3, "Half-Eaten Apple"],  [67, "Bowling Ball"],  [7, "Toothpaste"] ];   let result = updateInventory(curInv, newInv);  console.log(result); 

Комментарии:

1. Интересно, что на самом деле вопрос требует, чтобы вы обновили дубликаты текущих запасов, добавив в них количество новых запасов, рассматривая новые запасы как «доставку». В итоге я разработал несколько более простое решение, чем то, что у меня было раньше, но ваше гораздо более элегантное и приятное видение. Рад, что вы добавили комментарий