简体   繁体   English

如何根据嵌套数组中的值过滤带有对象的数组并对其进行计数

[英]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)

  • Get all the genres into a string array by using reduce使用reduce所有genres放入字符串数组中
  • sort the string array sort字符串数组进行sort
  • Use reduce to get the final object you need使用reduce得到你需要的最终对象
    • Inside this, check if the counter object already has a label for the current genre在这个里面,检查counter对象是否已经有当前genrelabel
    • if yes, increment it, else add a new object to the array如果是,则增加它,否则向数组中添加一个新对象

 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM