Создание списка покупок из массива ингредиентов (отформатированных как объекты)

E-Ron спросил: 13 июня 2018 в 10:58 в: javascript
var ingredients = [ 
  { name: 'potatoes', quantity: 4 },
  { name: 'butter', quantity: 1 },
  { name: 'milk', quantity: 1, description: '1 cup' },
  { name: 'potatoes', quantity: 3 },
  { name: 'oil', quantity: 1, description: '3 cups' } ];const shoppingList = [];for (let i = 0; i < ingredients.length; i ++) {
  for (let j = 0; j < shoppingList.length; j ++){
    let ingredient = ingredients[i];
    let shoppingListItem = shoppingList[j];
    if(ingredient === shoppingListItem){
      break;
    }else if (roughDraftItem.name === shoppingListItem.name){
      shoppingListItem.quantity += roughDraftItem.quantity;
      } else {shoppingList.push(roughDraftItem);
        }
    }
  }

Когда я запускаю этот код, массив shoppingList возвращается пустым. Когда я вынимаю второй цикл, у кода нет проблемы, и я получаю то, что мне нужно.

shoppingListItem = { name: 'potatoes', quantity: 1}

Кажется, что проблема заключается в попытке сравнить массив Ingredients с arrayList array (после добавления объекта).

3 ответа

LiRa ответил: 13 июня 2018 в 11:03

Ваш shoppingList пуст, поэтому его length = 0. Второй цикл массива не запускается, поскольку ему предлагается запустить 0 раз.

Второй цикл не нужен, чтобы добавить объект в shoppingList, поэтому я бы удалил его.

Alan Friedman ответил: 13 июня 2018 в 11:11

Как говорили другие, shoppingList начинается с длины 0, поэтому второй цикл никогда не будет запущен. Кроме того, если вы пытаетесь суммировать количество элементов с тем же именем, вы можете использовать reduce для упрощения:

const ingredients = [ 
  { name: 'potatoes', quantity: 4 },
  { name: 'butter', quantity: 1 },
  { name: 'milk', quantity: 1, description: '1 cup' },
  { name: 'potatoes', quantity: 3 },
  { name: 'oil', quantity: 1, description: '3 cups' } ];
  
const result = ingredients.reduce((acc, curr) => {
  const exists = acc.find(item => item.name === curr.name);
  if (exists) {
    exists.quantity += curr.quantity;
    return acc;
  }
  return [...acc, curr]
}, []);

console.log(result);
E-Ron ответил: 13 июня 2018 в 03:24
Благодаря! Быстрый вопрос заключался в том, что означает [... acc, curr]? Я не понимаю синтаксис ... и так как я не знаю его имени, мой поиск в Google не вызывает ответа
Alan Friedman ответил: 14 июня 2018 в 11:10
Да, он должен работать с любым количеством дубликатов
E-Ron ответил: 13 июня 2018 в 03:48
Кроме того, я вижу, как сокращение будет работать с этим массивом, поскольку картофель является единственным, который повторяется. Но будет ли это работать, если у меня будет несколько дубликатов? (то есть два масла, два молока и т. д.),
Alan Friedman ответил: 14 июня 2018 в 11:10
acc и curr относятся к аккумулятору и текущему значению
Leonid Pyrlia ответил: 14 июня 2018 в 08:25

Вы можете использовать Array.prototype.reduce и назначение объекта ES6 для создания агрегирования ингредиентов по их имени и Array.prototype.map для создания желаемого результата:

решение более декларативно, чем вложенные петли for, и может работать с любым количеством повторяющихся элементов:

var ingredients = [ 
  { name: 'potatoes', quantity: 4 },
  { name: 'butter', quantity: 1 },
  { name: 'milk', quantity: 1, description: '1 cup' },
  { name: 'potatoes', quantity: 3 },
  { name: 'oil', quantity: 1, description: '3 cups' }
];// Aggregate `quantity` by `name`
var dataObj = ingredients.reduce((all, {name, quantity}) => {
    all[name] = (all[name] || 0) + quantity;
    return all;
}, {});// Generate the result
var shoppingList = Object.keys(dataObj).map(ing => ({name: ing, quantity: dataObj[ing]}));console.log(shoppingList);

Дополнительное видео по вопросу: Создание списка покупок из массива ингредиентов (отформатированных как объекты)

Learn Javascript Programming #4: For Loops (Looping Through Numbers, Arrays, Objects)

JavaScript Nested Loops with Arrays and Objects

Search from array of objects in javascript