У меня есть массив объектов, которые выглядят так:
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 }
);
Пожалуйста, сделайте реальную попытку решить вашу проблему, тогда мы сможем помочь вам решить ее.
Если код в функции сокращения не ссылается на used
и available
, вы на самом деле не пытаетесь.
@Barmar, извините, вопрос был наполовину готов. я обновил его
Сначала сделайте 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()
Спасибо @Peter Thoeny. Если я хочу, чтобы доступные баллы были общими, как я могу это изменить? { доступно: 25, используется: 13}
@lrr97: см. ОБНОВЛЕНИЕ 1
Вы возвращаетесь на первую итерацию цикла. Вам нужно увеличить 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}
Просто делайте curr.available++
вне if
.
Вы можете сгладить массивы и добавить с помощью массива.
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}
Что такое
ob.tiles
? Ни в одном из ваших объектов нет свойстваtiles
. Похоже, вы просто скопировали этот код. Вы не пытались адаптировать его к вашей конкретной проблеме. Вы никогда не добавляете к свойствамavailable
иused
.