#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. Интересно, что на самом деле вопрос требует, чтобы вы обновили дубликаты текущих запасов, добавив в них количество новых запасов, рассматривая новые запасы как «доставку». В итоге я разработал несколько более простое решение, чем то, что у меня было раньше, но ваше гораздо более элегантное и приятное видение. Рад, что вы добавили комментарий