Сначала я сгладил массивы, а затем сосчитал до 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
для создания объекта, как в третьем фрагменте)