1

In the example below, I have an array of objects which contain some basic information about films - a film name and a personal rating.

Then i'm returning the duplicate values (using map and filter) to return new arrays and I can then count the number of items in that new array.

let films = [{
    "name": "film 1",
    "rating": "5",
}, {
    "name": "film 2",
    "rating": "1",
}, {
    "name": "film 3",
    "rating": "2",
}, {
    "name": "film 4",
    "rating": "2",
}, {
    "name": "film 5",
    "rating": "5",
}, {
    "name": "film 6",
    "rating": "4",
}];

let ratingsArray = films.map((element, i) => {
    return element.rating;
})
let arr0 = ratingsArray.filter((rating) => {
    return rating == 0;
})
let arr1 = ratingsArray.filter((rating) => {
    return rating == 1;
})
let arr2 = ratingsArray.filter((rating) => {
    return rating == 2;
})
let arr3 = ratingsArray.filter((rating) => {
    return rating == 3;
})
let arr4 = ratingsArray.filter((rating) => {
    return rating == 4;
})
let arr5 = ratingsArray.filter((rating) => {
    return rating == 5;
});

console.log(arr0);
console.log(arr1);
console.log(arr2);
console.log(arr3);
console.log(arr4);
console.log(arr5);

This does actually work but it seems a very repetitive way of writing this code.

Can anyone please suggest a better that I could be doing this?

2
  • do you want only the ratings in the arrays, not the whole objects? Commented Dec 17, 2017 at 16:50
  • At first look, let arr0 = films.filter((film) => { return film.rating == 0; }), should return all the films with 0 rating. You could wrap it around with a function that takes rating as an arguement Commented Dec 17, 2017 at 16:52

4 Answers 4

2

You could take an object and group the objects by rating.

var films = [{ name: "film 1", rating: "5", }, { name: "film 2", rating: "1", }, { name: "film 3", rating: "2", }, { name: "film 4", rating: "2", }, { name: "film 5", rating: "5", }, { name: "film 6", rating: "4", }],
    ratings = Object.create(null);

films.forEach(o => (ratings[o.rating] = ratings[o.rating] || []).push(o));

console.log(ratings);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

Comments

1

You can write a function that you can use as the callback in filter. It works similarly to how lodash's pluck method worked. pluck accepts a property key, and value and returns a closure that's used as the callback function when filter iterates over the elements in the array.

let films = [
  { "name": "film 1", "rating": "5" }, 
  { "name": "film 2", "rating": "1" }, 
  { "name": "film 3", "rating": "2" },
  { "name": "film 4", "rating": "2" },
  { "name": "film 5", "rating": "5" },
  { "name": "film 6", "rating": "4" }
];

function pluck(key, value) {
  return function (el) {
    return el[key] === value;
  }
}

const rating4 = films.filter(pluck('rating', '2'));
console.log(rating4);

You can then use this as you see fit, whether you want to loop over a set of ratings and store that information in an object, for example, but this is completely up to you. And you can use this function not just on this data set, but all sets where you need to pull out this kind of data.

let characters = [{
    "name": "Batman",
    "age": 62
}, {
    "name": "Supergirl",
    "age": 27
}, {
    "name": "Tarzan",
    "age": 102
}];

function pluck(key, value) {
  return function (el) {
    return el[key] === value;
  }
}

const tarzan = characters.filter(pluck('age', 102));
console.log(tarzan);

One thing tho: you might benefit from having the ratings as integers rather than strings. One thing to consider moving forward.

4 Comments

lodash doesn't have _.pluck anymore, they just say to use _.filter
So what you're saying is my answer is better than lodash?
Not necessarily (since you ask): I don't think your pluck function adds much value. Lodash got rid of _.pluck in favor of the more gernal _.filter I don't think they are meant to be used in combination as you do. My opinion, but you asked.
Well, it was sarcasm masked as a rhetorical question. But since the OP isn't using lodash (who loads a library for one method - I mentioned it passing) I disagree that my code doesn't add value. It's functional which means it can be used for similar datasets where you need to filter data.
0

You need to grouping the films by rating you can do using a object and arrays to store. See the example bellow:

let films = [{
    "name": "film 1",
    "rating": "5",
}, {
    "name": "film 2",
    "rating": "1",
}, {
    "name": "film 3",
    "rating": "2",
}, {
    "name": "film 4",
    "rating": "2",
}, {
    "name": "film 5",
    "rating": "5",
}, {
    "name": "film 6",
    "rating": "4",
}];
var filmsByRating = {};
//group films by rating
films.forEach((film) => {
   if(!filmsByRating[film.rating])
      filmsByRating[film.rating] = [];
   filmsByRating[film.rating].push(film);
});
//print ratings and films
for(var i in filmsByRating){
  console.log("Rating:", i);
  console.log(filmsByRating[i]);
}

Comments

0

I'm going to combine concepts from other answers and suggestions therein, and generate an Array, using reduce. Some advantages of putting the ratings into an Array instead of an Object include that you will then be able to perform useful Array methods such as reverse or (custom) sort e.g. maybe you want to sort by the rating that has the most films associated with it.

var films = [
    { name: "film 1", rating: "5", }, 
    { name: "film 2", rating: "1", }, 
    { name: "film 3", rating: "2", }, 
    { name: "film 4", rating: "2", }, 
    { name: "film 5", rating: "5", }, 
    { name: "film 6", rating: "4", }
];

var ratings = films.reduce(function(result, film) {
    var rating = parseInt(film.rating, 10);
    var ratedFilms = result[rating] || [];
    ratedFilms.push(film);
    result[rating] = ratedFilms;
    return result;
}, []);

ratings.forEach(function(rating, i) {
    console.log(i + ": " + JSON.stringify(rating));
});

RESULT:

1: [{"name":"film 2","rating":"1"}]
2: [{"name":"film 3","rating":"2"},{"name":"film 4","rating":"2"}]
4: [{"name":"film 6","rating":"4"}]
5: [{"name":"film 1","rating":"5"},{"name":"film 5","rating":"5"}]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.