结合不同的方法来计算嵌套列表中的元素
Combine different ways to count elements in nested lists
我有一个嵌套对象,我不仅想计算每个 point_name
出现的次数,而且我还想计算每个 point_name
属于多少类别。
dat = [
{name: "Category 1", points: [ {point_name: "A"}, {point_name: "B"}, {point_name: "C"} ]},
{name: "Category 2", points: [ {point_name: "A"}, {point_name: "B"}, {point_name: "D"} ]},
{name: "Category 3", points: [ {point_name: "A"}, {point_name: "D"}, {point_name: "E"} ]},
{name: "Category 4", points: [ {point_name: "F"}, {point_name: "G"}, {point_name: "C"}, {point_name: "G"} ]},
{name: "Category 5", points: [ {point_name: "A"}, {point_name: "B"}, {point_name: "H"}, {point_name: "H"} ]}
]
期望的输出
[
{name: "A", count: 4, categories: 4},
{name: "B", count: 3, categories: 3},
{name: "C", count: 2, categories: 2},
{name: "D", count: 2, categories: 2},
{name: "G", count: 2, categories: 1},
{name: "H", count: 2, categories: 1},
{name: "E", count: 1, categories: 1},
{name: "F", count: 1, categories: 1}
]
到目前为止我尝试了什么
我使用嵌套的 for 循环来获取所有 point_names
,因此我可以在 reduce
中使用它来计算每个 point_name
出现的次数,但我不能弄清楚如何计算每个 point_name
所在的类别数。
// double loop to get each point name
let counts = []
for (let i = 0; i < dat.length; i++) {
for (let j = 0; j < dat[i].points.length; j++) {
counts.push(dat[i].points[j].point_name)
}
}
// count their unique values
let uniques = counts.reduce((acc, val) => {
acc[val] = acc[val] === undefined ? 1 : acc[val] += 1;
return acc;
}, {});
// turn into array of objects
return Array(Object.keys(uniques).length)
.fill()
.map((x, i) => ({ name: Object.keys(uniques)[i], count: Object.values(uniques)[i] }))
感谢任何帮助!
您需要的是一个哈希表,用于保存遇到的每个类别的数量和数量。像这样。
var data = [
{name: "Category 1", points: [ {point_name: "A"}, {point_name: "B"}, {point_name: "C"} ]},
{name: "Category 2", points: [ {point_name: "A"}, {point_name: "B"}, {point_name: "D"} ]},
{name: "Category 3", points: [ {point_name: "A"}, {point_name: "D"}, {point_name: "E"} ]},
{name: "Category 4", points: [ {point_name: "F"}, {point_name: "G"}, {point_name: "C"}, {point_name: "G"} ]},
{name: "Category 5", points: [ {point_name: "A"}, {point_name: "B"}, {point_name: "H"}, {point_name: "H"} ]}
];
var hashTable = {};
data.forEach(d=>{
var points = d.points;
points.forEach(k=>{
if(hashTable[k.point_name]){
hashTable[k.point_name] ={
count: hashTable[k.point_name].count +1,
cat: [...hashTable[k.point_name].cat, d.name],
categoryCount: hashTable[k.point_name].cat.includes(d.name) ? hashTable[k.point_name].categoryCount : hashTable[k.point_name].categoryCount+1
}
}else{
hashTable[k.point_name] = {count: 1,
cat: [d.name],
categoryCount:1
}}
})
})
// console.log(hashTable);
var res = [];
Object.keys(hashTable).forEach(o=>{
res.push({
name: o,
count: hashTable[o].count,
categories: hashTable[o].categoryCount
})
});
console.log(res)
变换
[ {name: "Category 1", points: [ {point_name: "A"}
, {point_name: "B"}
, {point_name: "C"} ]}
, {name: "Category 2", points: [ {point_name: "A"}
, {point_name: "B"}
, {point_name: "D"} ]}
, {name: "Category 3", points: [ {point_name: "A"}
, {point_name: "D"}
, {point_name: "E"} ]}
, {name: "Category 4", points: [ {point_name: "F"}
, {point_name: "G"}
, {point_name: "C"}
, {point_name: "G"} ]}
, {name: "Category 5", points: [ {point_name: "A"}
, {point_name: "B"}
, {point_name: "H"}
, {point_name: "H"} ]}]
进入
[ {name: 'A', category: 'Category 1'}
, {name: 'B', category: 'Category 1'}
, {name: 'C', category: 'Category 1'}
, {name: 'A', category: 'Category 2'}
, {name: 'B', category: 'Category 2'}
, {name: 'D', category: 'Category 2'}
, {name: 'A', category: 'Category 3'}
, {name: 'D', category: 'Category 3'}
, {name: 'E', category: 'Category 3'}
, {name: 'F', category: 'Category 4'}
, {name: 'G', category: 'Category 4'}
, {name: 'C', category: 'Category 4'}
, {name: 'G', category: 'Category 4'}
, {name: 'A', category: 'Category 5'}
, {name: 'B', category: 'Category 5'}
, {name: 'H', category: 'Category 5'}
, {name: 'H', category: 'Category 5'}]
有
dat.flatMap(({name: category, points}) =>
points.map(p =>
({name: p.point_name, category})))
然后减少:
….reduce((acc, p) => {
acc[p.name] ??= [0, new Set];
acc[p.name][0] += 1;
acc[p.name][1].add(p.category);
return acc;
}, {}))
这给了你这个:
将所有内容放在一起:
console.log(
Object
.entries(
dat
.flatMap(({name: category, points}) =>
points.map(p =>
({name: p.point_name, category})))
.reduce((acc, p) => {
acc[p.name] ??= [0, new Set];
acc[p.name][0] += 1;
acc[p.name][1].add(p.category);
return acc;
}, {}))
.map(([name, [count, categories]]) =>
({name, count, categories: categories.size}))
)
<script>
var dat =
[ {name: "Category 1", points: [ {point_name: "A"}
, {point_name: "B"}
, {point_name: "C"} ]}
, {name: "Category 2", points: [ {point_name: "A"}
, {point_name: "B"}
, {point_name: "D"} ]}
, {name: "Category 3", points: [ {point_name: "A"}
, {point_name: "D"}
, {point_name: "E"} ]}
, {name: "Category 4", points: [ {point_name: "F"}
, {point_name: "G"}
, {point_name: "C"}
, {point_name: "G"} ]}
, {name: "Category 5", points: [ {point_name: "A"}
, {point_name: "B"}
, {point_name: "H"}
, {point_name: "H"} ]}]
</script>
我有一个嵌套对象,我不仅想计算每个 point_name
出现的次数,而且我还想计算每个 point_name
属于多少类别。
dat = [
{name: "Category 1", points: [ {point_name: "A"}, {point_name: "B"}, {point_name: "C"} ]},
{name: "Category 2", points: [ {point_name: "A"}, {point_name: "B"}, {point_name: "D"} ]},
{name: "Category 3", points: [ {point_name: "A"}, {point_name: "D"}, {point_name: "E"} ]},
{name: "Category 4", points: [ {point_name: "F"}, {point_name: "G"}, {point_name: "C"}, {point_name: "G"} ]},
{name: "Category 5", points: [ {point_name: "A"}, {point_name: "B"}, {point_name: "H"}, {point_name: "H"} ]}
]
期望的输出
[
{name: "A", count: 4, categories: 4},
{name: "B", count: 3, categories: 3},
{name: "C", count: 2, categories: 2},
{name: "D", count: 2, categories: 2},
{name: "G", count: 2, categories: 1},
{name: "H", count: 2, categories: 1},
{name: "E", count: 1, categories: 1},
{name: "F", count: 1, categories: 1}
]
到目前为止我尝试了什么
我使用嵌套的 for 循环来获取所有 point_names
,因此我可以在 reduce
中使用它来计算每个 point_name
出现的次数,但我不能弄清楚如何计算每个 point_name
所在的类别数。
// double loop to get each point name
let counts = []
for (let i = 0; i < dat.length; i++) {
for (let j = 0; j < dat[i].points.length; j++) {
counts.push(dat[i].points[j].point_name)
}
}
// count their unique values
let uniques = counts.reduce((acc, val) => {
acc[val] = acc[val] === undefined ? 1 : acc[val] += 1;
return acc;
}, {});
// turn into array of objects
return Array(Object.keys(uniques).length)
.fill()
.map((x, i) => ({ name: Object.keys(uniques)[i], count: Object.values(uniques)[i] }))
感谢任何帮助!
您需要的是一个哈希表,用于保存遇到的每个类别的数量和数量。像这样。
var data = [
{name: "Category 1", points: [ {point_name: "A"}, {point_name: "B"}, {point_name: "C"} ]},
{name: "Category 2", points: [ {point_name: "A"}, {point_name: "B"}, {point_name: "D"} ]},
{name: "Category 3", points: [ {point_name: "A"}, {point_name: "D"}, {point_name: "E"} ]},
{name: "Category 4", points: [ {point_name: "F"}, {point_name: "G"}, {point_name: "C"}, {point_name: "G"} ]},
{name: "Category 5", points: [ {point_name: "A"}, {point_name: "B"}, {point_name: "H"}, {point_name: "H"} ]}
];
var hashTable = {};
data.forEach(d=>{
var points = d.points;
points.forEach(k=>{
if(hashTable[k.point_name]){
hashTable[k.point_name] ={
count: hashTable[k.point_name].count +1,
cat: [...hashTable[k.point_name].cat, d.name],
categoryCount: hashTable[k.point_name].cat.includes(d.name) ? hashTable[k.point_name].categoryCount : hashTable[k.point_name].categoryCount+1
}
}else{
hashTable[k.point_name] = {count: 1,
cat: [d.name],
categoryCount:1
}}
})
})
// console.log(hashTable);
var res = [];
Object.keys(hashTable).forEach(o=>{
res.push({
name: o,
count: hashTable[o].count,
categories: hashTable[o].categoryCount
})
});
console.log(res)
变换
[ {name: "Category 1", points: [ {point_name: "A"}
, {point_name: "B"}
, {point_name: "C"} ]}
, {name: "Category 2", points: [ {point_name: "A"}
, {point_name: "B"}
, {point_name: "D"} ]}
, {name: "Category 3", points: [ {point_name: "A"}
, {point_name: "D"}
, {point_name: "E"} ]}
, {name: "Category 4", points: [ {point_name: "F"}
, {point_name: "G"}
, {point_name: "C"}
, {point_name: "G"} ]}
, {name: "Category 5", points: [ {point_name: "A"}
, {point_name: "B"}
, {point_name: "H"}
, {point_name: "H"} ]}]
进入
[ {name: 'A', category: 'Category 1'}
, {name: 'B', category: 'Category 1'}
, {name: 'C', category: 'Category 1'}
, {name: 'A', category: 'Category 2'}
, {name: 'B', category: 'Category 2'}
, {name: 'D', category: 'Category 2'}
, {name: 'A', category: 'Category 3'}
, {name: 'D', category: 'Category 3'}
, {name: 'E', category: 'Category 3'}
, {name: 'F', category: 'Category 4'}
, {name: 'G', category: 'Category 4'}
, {name: 'C', category: 'Category 4'}
, {name: 'G', category: 'Category 4'}
, {name: 'A', category: 'Category 5'}
, {name: 'B', category: 'Category 5'}
, {name: 'H', category: 'Category 5'}
, {name: 'H', category: 'Category 5'}]
有
dat.flatMap(({name: category, points}) =>
points.map(p =>
({name: p.point_name, category})))
然后减少:
….reduce((acc, p) => {
acc[p.name] ??= [0, new Set];
acc[p.name][0] += 1;
acc[p.name][1].add(p.category);
return acc;
}, {}))
这给了你这个:
将所有内容放在一起:
console.log(
Object
.entries(
dat
.flatMap(({name: category, points}) =>
points.map(p =>
({name: p.point_name, category})))
.reduce((acc, p) => {
acc[p.name] ??= [0, new Set];
acc[p.name][0] += 1;
acc[p.name][1].add(p.category);
return acc;
}, {}))
.map(([name, [count, categories]]) =>
({name, count, categories: categories.size}))
)
<script>
var dat =
[ {name: "Category 1", points: [ {point_name: "A"}
, {point_name: "B"}
, {point_name: "C"} ]}
, {name: "Category 2", points: [ {point_name: "A"}
, {point_name: "B"}
, {point_name: "D"} ]}
, {name: "Category 3", points: [ {point_name: "A"}
, {point_name: "D"}
, {point_name: "E"} ]}
, {name: "Category 4", points: [ {point_name: "F"}
, {point_name: "G"}
, {point_name: "C"}
, {point_name: "G"} ]}
, {name: "Category 5", points: [ {point_name: "A"}
, {point_name: "B"}
, {point_name: "H"}
, {point_name: "H"} ]}]
</script>