Объединить значение объекта, содержащее массив: Javascript

У меня есть массив объектов, которые выглядят так:

const test = {
  cat1: {
    id: "c1",
    name: "category1",
    items: [
      {
        itemName: "item1",
        points: 1,
        used: true
      },
      {
        itemName: "item2",
        points: 3,
        used: false
      },
      {
        itemName: "item3",
        points: 5,
        used: true
      }
    ]
  },
  cat2: {
    id: "c2",
    name: "category2",
    items: [
      {
        itemName: "item4",
        points: 7,
        used: true
      },
      {
        itemName: "item5",
        points: 9,
        used: false
      }
    ]
  },
  cat3: {
    id: "c3",
    name: "category3",
    items: [
      {
        itemName: "item6"
      }
    ]
  }
};

Я хочу, чтобы вывод был чем-то вроде этого

{ available: 12 , used: 13}

Нужно просмотреть массив элементов и получить available и used на основе логического значения used для каждого объекта. Если это правда, добавьте его с помощью used, иначе добавьте с помощью записи available. Некоторые объекты могут не иметь points и used, их нужно игнорировать.

Может кто поможет с подходом

Код, который я пробовал


const result = Object.values(test).reduce(
  (acc, obj) => {
    for (let i = 0; i < obj.items.length; i++) {
      if (obj.items[i].used) {
        return (acc.used = acc.used + obj.items[i].used);
      } else acc.available = acc.available + obj.items[i].available;
    }
  },
  { available: 0, used: 0 }
);

Что такое ob.tiles? Ни в одном из ваших объектов нет свойства tiles. Похоже, вы просто скопировали этот код. Вы не пытались адаптировать его к вашей конкретной проблеме. Вы никогда не добавляете к свойствам available и used.

Barmar 14.02.2023 20:31

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

Barmar 14.02.2023 20:32

Если код в функции сокращения не ссылается на used и available, вы на самом деле не пытаетесь.

Barmar 14.02.2023 20:33

@Barmar, извините, вопрос был наполовину готов. я обновил его

lrr97 14.02.2023 20:37
Типы данных JavaScript
Типы данных JavaScript
В JavaScript существует несколько типов данных, включая примитивные типы данных и ссылочные типы данных. Вот краткое объяснение различных типов данных...
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик Модуль flexbox, также известный как гибкий модуль разметки box, помогает эффективно проектировать и...
Введение в раздел &quot;Заголовок&quot; в HTML
Введение в раздел "Заголовок" в HTML
Говорят, что лучшее о человеке можно увидеть только изнутри, и это относится и к веб-страницам HTML! Причина, по которой некоторые веб-страницы не...
Как React Helmet спасает меня при разделении файлов CSS?
Как React Helmet спасает меня при разделении файлов CSS?
Многие новички могут столкнуться с проблемой, когда одна страница с CSS наследует свойства от другой страницы с другим CSS. У меня было много проблем,...
Потяните за рычаг выброса энергососущих проектов
Потяните за рычаг выброса энергососущих проектов
На этой неделе моя команда отменила проект, над которым я работал. Неделя усилий пошла насмарку.
Руководство для начинающих по веб-разработке: HTML, CSS и JavaScript.
Руководство для начинающих по веб-разработке: HTML, CSS и JavaScript.
Добро пожаловать, мои коллеги по интернету, в захватывающий мир веб-разработки! Дорогие мои начинающие, я здесь, чтобы провести вас через основы HTML,...
1
4
60
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Сначала сделайте map() и .flat(), затем .reduce():

const input = { cat1: { id: "c1", name: "category1", items: [ { itemName: "item1", points: 1, used: true }, { itemName: "item2", points: 3, used: false }, { itemName: "item3", points: 5, used: true } ] }, cat2: { id: "c2", name: "category2", items: [ { itemName: "item4", points: 7, used: true }, { itemName: "item5", points: 9, used: false } ] }, cat3: { id: "c3", name: "category3", items: [ { itemName: "item6" } ] } };

const result = Object.values(input).map(obj => obj.items).flat().reduce((acc, obj) => {
  if (obj.used) {
    acc.used += obj.points;
  } else {
    acc.available += obj.points || 0;
  }
  return acc;
}, {available: 0, used: 0})
console.info(result);

Выход:

{
  "available": 12,
  "used": 13
}

ОБНОВЛЕНИЕ 1, чтобы получить общие баллы за доступные:

const input = { cat1: { id: "c1", name: "category1", items: [ { itemName: "item1", points: 1, used: true }, { itemName: "item2", points: 3, used: false }, { itemName: "item3", points: 5, used: true } ] }, cat2: { id: "c2", name: "category2", items: [ { itemName: "item4", points: 7, used: true }, { itemName: "item5", points: 9, used: false } ] }, cat3: { id: "c3", name: "category3", items: [ { itemName: "item6" } ] } };

const result = Object.values(input).map(obj => obj.items).flat().reduce((acc, obj) => {
  acc.available += obj.points || 0;
  if (obj.used) {
    acc.used += obj.points;
  }
  return acc;
}, {available: 0, used: 0})
console.info(result);

Выход:

{
  "available": 25,
  "used": 13
}

Вы можете комбинировать map и flat с .flatmap()

Barmar 14.02.2023 20:47

Спасибо @Peter Thoeny. Если я хочу, чтобы доступные баллы были общими, как я могу это изменить? { доступно: 25, используется: 13}

lrr97 14.02.2023 21:18

@lrr97: см. ОБНОВЛЕНИЕ 1

Peter Thoeny 14.02.2023 21:26

Вы возвращаетесь на первую итерацию цикла. Вам нужно увеличить acc.used или acc.available в цикле, но вернуть acc только в конце цикла.

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

Obj.items[i].used - это не число, которое нужно добавить. Вы должны просто увеличить счетчик. А obj.items[i].available нет.

const test = {
  cat1: {
    id: "c1",
    name: "category1",
    items: [{
        itemName: "item1",
        points: 1,
        used: true
      },
      {
        itemName: "item2",
        points: 3,
        used: false
      },
      {
        itemName: "item3",
        points: 5,
        used: true
      }
    ]
  },
  cat2: {
    id: "c2",
    name: "category2",
    items: [{
        itemName: "item4",
        points: 7,
        used: true
      },
      {
        itemName: "item5",
        points: 9,
        used: false
      }
    ]
  },
  cat3: {
    id: "c3",
    name: "category3",
    items: [{
      itemName: "item6"
    }]
  }
};

const result = Object.values(test).reduce(
  (curr, obj) => {
    obj.items.forEach(item => {
      if (item.used) {
        curr.used++;
      } else {
        curr.available++;
      }
    });
    return curr;
  }, {
    available: 0,
    used: 0
  });

console.info(result);

Спасибо @Barmar. В случае, если я хочу, чтобы доступными были общие баллы, как я могу это изменить? { доступно: 25, используется: 13}

lrr97 14.02.2023 21:18

Просто делайте curr.available++ вне if.

Barmar 14.02.2023 21:33
Ответ принят как подходящий

Вы можете сгладить массивы и добавить с помощью массива.

const
    test = { cat1: { id: "c1", name: "category1", items: [{ itemName: "item1", points: 1, used: true }, { itemName: "item2", points: 3, used: false }, { itemName: "item3", points: 5, used: true }] }, cat2: { id: "c2", name: "category2", items: [{ itemName: "item4", points: 7, used: true }, { itemName: "item5", points: 9, used: false }] }, cat3: { id: "c3", name: "category3", items: [{ itemName: "item6" }] } },
    result = Object
        .values(test)
        .flatMap(({ items }) => items)
        .reduce((r, { points, used }) => {
            if (points) r[['available', 'used'][+used]] += points;
            return r;
        }, { available: 0 , used: 0 });

console.info(result);

2-й запрос.

const
    test = { cat1: { id: "c1", name: "category1", items: [{ itemName: "item1", points: 1, used: true }, { itemName: "item2", points: 3, used: false }, { itemName: "item3", points: 5, used: true }] }, cat2: { id: "c2", name: "category2", items: [{ itemName: "item4", points: 7, used: true }, { itemName: "item5", points: 9, used: false }] }, cat3: { id: "c3", name: "category3", items: [{ itemName: "item6" }] } },
    result = Object
        .values(test)
        .flatMap(({ items }) => items)
        .reduce((r, { points = 0, used = false }) => {
            r.used += used && points;
            r.available += points;
            return r;
        }, { available: 0 , used: 0 });

console.info(result);

Спасибо @Nina Scholz, если я хочу, чтобы доступные баллы были общими, как я могу это изменить? { доступно: 25, используется: 13}

lrr97 14.02.2023 21:18

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

Суммируйте цены из массива, пока они не будут соответствовать определенному значению, которое определено в другом массиве.
Разобрать отформатированную строку с метками, написанными ЗАГЛАВНЫМИ БУКВАМИ, за которыми следует их значение, для создания ассоциативного массива.
Массив не расширяется при использовании в if
Создание таблицы из массива в React
Изменение вхождений значения в матрице
Почему адреса распределенного 2D-массива не такие, как я ожидаю?
Является ли мелкая копия массива дешевой, независимо от размера?
Сортировка слиянием в C возвращает список, содержащий дубликаты одних и тех же 3-4 чисел. Другие номера отсутствуют в отсортированном списке
Я застрял. Мне нужно настроить свои циклы, чтобы они продолжали сравнивать два моих массива, но не распечатывали все лишние символы.
Можно ли в C написать в одной строке вызов функции, которая имеет массив строк (т.е. ptr) или int, или... в качестве параметра?