javascript - 在对象数组中创建唯一列表和数组项计数
问题描述
我有以下源数组:
const list = [
{
students: [ 'peter', 'bob', 'john']
},
{
students: [ 'thomas', 'sarah', 'john']
},
{
students: [ 'john', 'sarah', 'jack']
}
];
我想得到唯一的学生姓名和他们的人数,最终结果应该是这样的:
{
'john': 3,
'sarah': 2,
'thomas': 1,
'jack': 1,
'peter': 1,
'bob': 1
}
这是我的尝试:
const unique = list.reduce(function(total, curr){
const students = curr.students;
for (c of students) {
if (!total[c]) {
total[c] = 1
} else {
total[c] += 1;
}
}
return total;
}, {});
有更好的方法吗?还是更快更清洁的方式?谢谢
解决方案
我会先展平阵列,然后计算reduce
:
const list = [
{
students: [ 'peter', 'bob', 'john']
},
{
students: [ 'thomas', 'sarah', 'john']
},
{
students: [ 'john', 'sarah', 'jack']
}
];
const allStudents = list.flatMap(({ students }) => students);
const count = allStudents.reduce((a, name) => {
a[name] = (a[name] || 0) + 1;
return a;
}, {});
console.log(count);
如果您还希望对属性进行排序,则获取Object.entries
对象的 ,对其进行排序,然后将其转回具有 的对象Object.fromEntries
:
const list = [
{
students: [ 'peter', 'bob', 'john']
},
{
students: [ 'thomas', 'sarah', 'john']
},
{
students: [ 'john', 'sarah', 'jack']
}
];
const allStudents = list.flatMap(({ students }) => students);
const count = allStudents.reduce((a, name) => {
a[name] = (a[name] || 0) + 1;
return a;
}, {});
const sorted = Object.fromEntries(
Object.entries(count).sort((a, b) => b[1] - a[1])
);
console.log(sorted);
如果您的环境不支持 flatMap 或 fromEntries,请使用 polyfill 或 flatten/group 使用不同的方法:
const list = [
{
students: [ 'peter', 'bob', 'john']
},
{
students: [ 'thomas', 'sarah', 'john']
},
{
students: [ 'john', 'sarah', 'jack']
}
];
const allStudents = [].concat(...list.map(({ students }) => students));
const count = allStudents.reduce((a, name) => {
a[name] = (a[name] || 0) + 1;
return a;
}, {});
const sortedEntries = Object.entries(count).sort((a, b) => b[1] - a[1]);
const sortedObj = sortedEntries.reduce((a, [prop, val]) => {
a[prop] = val;
return a;
}, {});
console.log(sortedObj);
请记住,对象属性顺序仅在 ES6+ 环境中指定。虽然Object.fromEntries
规范不保证以与条目相同的顺序创建对象,但幸运的是,在我遇到的任何实现中,它无论如何都可以。(如果您仍然担心它,您可以使用老式reduce
方法来创建对象,就像在第三个片段中一样)
推荐阅读
- amazon-s3 - 从一个 AWS 子账户流式传输 S3 文件,Flink 部署在另一个 AWS 账户的 Kubernetes 集群上
- alert - Grafana:如何根据两个事件创建警报?
- c# - 从 OpenApi.json 生成 C# 客户端
- r - 如何使用 ggplot 创建具有共享 x 轴的背靠背图?
- typescript - 如何使用该 xpath 对元素设置操作?
- laravel - Laravel 5.8 请求数据为空
- android - GridView 没有全屏显示
- angular - Mat-Button routerLinkActive 替代方案?
- command-line - 意外标记“(”附近的语法错误,带有 gdbserver 的引用参数
- react-native - React native error "unsupported BodyInit type" 为什么会出现以及如何解决?