Объединить значение объекта, содержащее массив: 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
Поведение ключевого слова "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
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, или... в качестве параметра?