1

Write a function named sort_by_average_rating that takes a list/array of key-value stores as a parameter where each key-value store has keys ratings, budget, and box_office where budget and box_office are integers and ratings is a list of integers. Sort the input based on the average of the values in ratings.

I tried adding everything within a for loop when the key is equal to ["ratings"] then after that, I average the results from the two for loops. Lastly, I used a separate function to sort everything.

function key(a,b){
  for(var i = 0; i < a.length; i++){
    tol1 += a[i]["ratings"];  

  for(var x = 0; x < b.length; x++) {
    tol2 += b[x]["ratings"];
    }
    var average = (tol1/tol2);
  }
  return average;
}

function key(x,y){
  if (x[key] < x[key]) { return -1; }
  if (y[key] > y[key]) { return 1; }
  return 0;
 }

function sort_by_average_rating(b){
  b.sort(key)
 }

Result:

[
    {'box_office': 12574015, 'budget': 3986053.18, 'ratings': [8, 7, 1]}, 
    {'box_office': 44855251, 'budget': 3301717.62, 'ratings': [7, 1, 1]}, 
    {'box_office': 36625133, 'budget': 8678591, 'ratings': [7, 6, 2, 8]}, 
    {'box_office': 48397691, 'budget': 15916122.88, 'ratings': [7, 3, 8, 8, 6, 8]}, 
    {'box_office': 43344800, 'budget': 4373679.25, 'ratings': [1, 1, 7, 4]}
]

Expected:

[
    {'box_office': 44855251, 'budget': 3301717.62, 'ratings': [7, 1, 1]}, 
    {'box_office': 43344800, 'budget': 4373679.25, 'ratings': [1, 1, 7, 4]}, 
    {'box_office': 12574015, 'budget': 3986053.18, 'ratings': [8, 7, 1]}, 
    {'box_office': 36625133, 'budget': 8678591.0, 'ratings': [7, 6, 2, 8]}, 
    {'box_office': 48397691, 'budget': 15916122.88, 'ratings': [7, 3, 8, 8, 6, 8]}
]
1
  • 3
    You have two function key(). Only the second definition is used, the first one is overwritten. Actually, that's just the tip of the iceberg... key inside the function is still referring to the function itself. Commented Apr 23, 2019 at 18:21

3 Answers 3

3

One possible solution is to create a function that return the average of a ratings array, we going to use Array.reduce() for this one. Then you can use this new function with the built-in Array.sort() to generate your desired result:

const input = [
  {'box_office': 12574015, 'budget': 3986053.18, 'ratings': [8, 7, 1]},
  {'box_office': 44855251, 'budget': 3301717.62, 'ratings': [7, 1, 1]},
  {'box_office': 36625133, 'budget': 8678591, 'ratings': [7, 6, 2, 8]},
  {'box_office': 48397691, 'budget': 15916122.88, 'ratings': [7, 3, 8, 8, 6, 8]},
  {'box_office': 43344800, 'budget': 4373679.25, 'ratings': [1, 1, 7, 4]}
];

const getAverage = (arr) =>
{
    return (Array.isArray(arr) && arr.length > 0) ?
           arr.reduce((acc, n) => acc + n) / arr.length :
           0;
};

input.sort((a, b) => getAverage(a.ratings) - getAverage(b.ratings));
console.log(input);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

To avoid mutation of the original data, use:

let sorted = input.slice().sort((a, b) => getAverage(a.ratings) - getAverage(b.ratings));
Sign up to request clarification or add additional context in comments.

2 Comments

Would help to pass an initial value of 0 to reduce() in case there are no ratings... though then the result would be NaN. 0/0 is indeterminate.
@PatrickRoberts Thanks for the feedback, I have updated the code.
3

I suggest to use a different approach (sorting with map) by taking the averages in an array and another array for the indices, sort the indices array and map the objects by taking the indices.

const add = (a, b) => a + b;

var array = [{ box_office: 12574015, budget: 3986053.18, ratings: [8, 7, 1] }, { box_office: 44855251, budget: 3301717.62, ratings: [7, 1, 1] }, { box_office: 36625133, budget: 8678591, ratings: [7, 6, 2, 8] }, { box_office: 48397691, budget: 15916122.88, ratings: [7, 3, 8, 8, 6, 8] }, { box_office: 43344800, budget: 4373679.25, ratings: [1, 1, 7, 4] }],
    averages = array.map(({ ratings }) => ratings.reduce(add, 0) / ratings.length),
    indices = [...averages.keys()].sort((i, j) => averages[i] - averages[j]),
    result = indices.map(i => array[i]);
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

2

1) you should initialize your variables before using them (e.g. tol1

2) you should avoid repeating function names (e.g. key)

3) you should name your variables and functions something meaningful (e.g. 'a', 'b', 'key', 'x', 'y') mean nothing.

let movies = [
  {'box_office': 12574015, 'budget': 3986053.18, 'ratings': [8, 7, 1]},
  {'box_office': 44855251, 'budget': 3301717.62, 'ratings': [7, 1, 1]},
  {'box_office': 36625133, 'budget': 8678591, 'ratings': [7, 6, 2, 8]},
  {'box_office': 48397691, 'budget': 15916122.88, 'ratings': [7, 3, 8, 8, 6, 8]},
  {'box_office': 43344800, 'budget': 4373679.25, 'ratings': [1, 1, 7, 4]}
];

let averageRating = movie => 
    movie.ratings.reduce((rating, sum) => rating + sum, 0) / movie.ratings.length;

let sortedMovies = movies.sort((movie1, movie2) => averageRating(movie1) - averageRating(movie2));

console.log(sortedMovies);

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.