Этого можно добиться, поместив все массивы genre
в массив, а затем сгладив этот массив, используя .flat()
.После этого вы можете использовать .reduce
для создания массива объектов из этого массива.
См. Рабочий пример ниже (см. Комментарии к коду для дальнейшего объяснения):
const movies= [{title:"Movie A",genre:["Action","Sci-Fi","Thriller"]},{title:"Movie B",genre:["Horror","Sci-Fi"]},{title:"Movie C",genre:["Action","Horror","Thriller"]},{title:"Movie D",genre:["Mystery","Horror","Sci-Fi"]}];
res = movies.map(({genre}) => genre) // create array of genres (multi-dimensonal)
.flat() // flatten the array of arrays to only have genres in it
.sort((a,b) => a.localeCompare(b)) // sort the array alphabetically
.reduce((acc, genre) => {
let i = acc.length-1 // get the previous index of the last object
let prev = acc[i]; // get the previous object
if(prev && prev.label == genre) { // if the previous label is equal to the curren genre than:
acc[i].count++; // add one to the current objects count
} else { // otherwise...
acc = [...acc, {label: genre, count: 1}]; // append a new object to the accumilator
}
return acc; // return the result of the accumilator to be used in next iteration
}, []); // set starting value of reduce to empty array
console.log(res);
В качестве альтернативы, если вы не можете позволить себе использовать метод .flat()
, вы можете использовать следующее:
const movies= [{title:"Movie A",genre:["Action","Sci-Fi","Thriller"]},{title:"Movie B",genre:["Horror","Sci-Fi"]},{title:"Movie C",genre:["Action","Horror","Thriller"]},{title:"Movie D",genre:["Mystery","Horror","Sci-Fi"]}];
res = [].concat.apply([], movies.map(({genre}) => genre))
.sort((a,b) => a.localeCompare(b))
.reduce((acc, genre) => {
let i = acc.length-1
let prev = acc[i];
if(prev && prev.label == genre) {
acc[i].count++;
} else {
acc = [...acc, {label: genre, count: 1}];
}
return acc;
}, []);
console.log(res);