每个父元素应包含所有子类别的总数。如果解决方案仅使用 Array对象方法而不使用while
循环,那将是非常好的。
这是基本结构的示例:
const base = [
{ id: 1, count: 2, parentId: null },
{ id: 2, count: 4, parentId: 1 },
{ id: 3, count: 0, parentId: 2 },
{ id: 6, count: 8, parentId: 3 },
{ id: 7, count: 8, parentId: 3 },
{ id: 8, count: 2, parentId: 7 },
{ id: 4, count: 2, parentId: null },
{ id: 5, count: 1, parentId: 4 },
];
它应该是这样的:
const expected = [
{ id: 1, count: 2, total: 24, parentId: null },
{ id: 2, count: 4, total: 22, parentId: 1 },
{ id: 3, count: 0, total: 18, parentId: 2 },
{ id: 6, count: 8, total: 8, parentId: 3 },
{ id: 7, count: 8, total: 10, parentId: 3 },
{ id: 8, count: 2, total: 2, parentId: 7 },
{ id: 4, count: 2, total: 3, parentId: null },
{ id: 5, count: 1, total: 1, parentId: 4 },
];
这是我当前的代码。我认为在某种程度上我需要进入最后一个层次
然后从最后一项开始,到当前的最高水平
级别count
的支持价值,这就是为什么我将其命名为IIFE。
let c = a.map(cat => {
const top = a.filter(v => cat.id === v.parentId);
let test;
return ({
...cat,
total: (test = categs => {
return categs.reduce((acc, val) => {
/* ??? */
return acc + val.count
}, cat.count);
})(top)
})
})
答案 0 :(得分:2)
在这里刺伤
const base = [
{ id: 1, count: 2, parentId: null },
{ id: 2, count: 4, parentId: 1 },
{ id: 3, count: 0, parentId: 2 },
{ id: 6, count: 8, parentId: 3 },
{ id: 7, count: 8, parentId: 3 },
{ id: 8, count: 2, parentId: 7 },
{ id: 4, count: 2, parentId: null },
{ id: 5, count: 1, parentId: 4 },
];
const getDescendants = ({ id }) =>
base.reduce((acc, n) => n.parentId === id ? [...acc, n, ...getDescendants(n)] : acc, []);
const expected =
base.map(record => ({
...record,
total: getDescendants(record).reduce((acc, cur) => acc + cur.count, record.count)
}));
console.log(expected);
这里的真正窍门是getDescendants
函数。通过递归应用该函数,它会得到一个数组,其中所有元素的parentId
属性等于当前记录的id
并与该节点的所有后代串联在一起。
该解决方案效率不高,但是鉴于该问题明确禁止使用某些核心编程构造,因此我怀疑这是必要条件。
这是另一种方法,以递归方式修改原始数组:
const base = [
{ id: 1, count: 2, parentId: null },
{ id: 2, count: 4, parentId: 1 },
{ id: 3, count: 0, parentId: 2 },
{ id: 6, count: 8, parentId: 3 },
{ id: 7, count: 8, parentId: 3 },
{ id: 8, count: 2, parentId: 7 },
{ id: 4, count: 2, parentId: null },
{ id: 5, count: 1, parentId: 4 },
];
const addToTotal = (id, count) => id !== null && base.forEach(n => {
if (n.id === id) {
n.total = (n.total || 0) + count;
addToTotal(n.parentId, count);
}
});
base.forEach(n => {
n.total = (n.total || 0) + n.count;
addToTotal(n.parentId, n.count);
});
console.log(base);
答案 1 :(得分:1)
如果您的收藏集已经排序并且仅需要计算总数。我带着reduceRight
来保存循环数并避免突变。
const base = [
{ id: 1, count: 2, parentId: null },
{ id: 2, count: 4, parentId: 1 },
{ id: 3, count: 0, parentId: 2 },
{ id: 6, count: 8, parentId: 3 },
{ id: 7, count: 8, parentId: 3 },
{ id: 8, count: 2, parentId: 7 },
{ id: 4, count: 2, parentId: null },
{ id: 5, count: 1, parentId: 4 },
];
const rs = base.reduceRight((acc, o) => {
const total = acc.filter(n => n.parentId === o.id).reduce((x, y) => x + y.total, 0)
return acc.concat({...o, total: total + o.count})
}, [])
console.log(rs.reverse());