[英]How to filter array with objects based on values in nested array and counting them
I have a movies array
with objects
listing genres (as an array
) for each movie:我有一个电影
array
其中objects
列出每部电影的流派(作为array
)的objects
:
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"]
}
];
Using (vanilla, ES6+ or Lodash) JavaScript: How do I create a new array
(see below) with objects
showing how many times ( count
below) a genre ( label
below) is listed in above movies genre
array?使用(vanilla、ES6+ 或 Lodash)JavaScript:如何创建一个新
array
(见下文),其中的objects
显示上面电影genre
数组中列出了多少次(下面count
)类型(下面的label
)?
In other words: how many times a genre is listed above.换句话说:上面列出了一个类型的次数。
End result : a new array
sorted alphabeticaly by label
:最终结果:按
label
字母顺序排序的新array
:
const genres = [
{
"label": "Action",
"count": 2
},
{
"label": "Horror",
"count": 3
},
{
"label": "Mystery",
"count": 1
},
{
"label": "Sci-Fi",
"count": 3
},
{
"label": "Thriller",
"count": 2
}
];
You can achieve this by putting all the genre
arrays into an array and then flattening that array using .flat()
.您可以通过将所有
genre
数组放入一个数组中,然后使用.flat()
将该数组.flat()
平来实现这一点。 After that you can then use .reduce
to create an array of objects from this array.之后,您可以使用
.reduce
从该数组创建一个对象数组。
See working example below (read code comments for further explanation):请参阅下面的工作示例(阅读代码注释以获取进一步说明):
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);
Alternatively, if you cannot afford to use the .flat()
method you can use the following instead:或者,如果您负担不起使用
.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);
This will create the array with the labels and the count这将创建带有标签和计数的数组
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"] } ]; var genres = []; for (var i = 0; i < movies.length; i++) { var list = movies[i].genre; for (var j = 0; j < list.length; j++) { var existingValue = genres.find(function (value) { return value.label === list[j] }); if (!existingValue) { genres.push( { label: list[j], count: 1 } ); } else { existingValue.count++; } } } console.log(genres)
genres
into a string array by using reduce
reduce
所有genres
放入字符串数组中sort
the string array sort
字符串数组进行sort
reduce
to get the final object you needreduce
得到你需要的最终对象
counter
object already has a label
for the current genre
counter
对象是否已经有当前genre
的label
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"]}]; const final = movies.reduce((genres, {genre}) => genres.concat(genre), []) .sort() .reduce((counter, genre) => { const item = counter.find(c => c.label === genre); item ? item["count"]++ : counter.push({ label:genre, count:1 }); return counter }, []); console.log(final);
Or you can create an object with each genre
as key and the value as the object you need in the final array.或者,您可以创建一个对象,将每个
genre
作为键,并将值作为最终数组中所需的对象。 Then use Object.values
to get the desired output:然后使用
Object.values
获得所需的输出:
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"]}]; const final = movies .map(a => a.genre) .flat() .sort() .reduce((a, label) => ((a[label] = a[label] || {label, count: 0})["count"]++,a), {}); console.log(Object.values(final));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.