Trying to combine two datasets where object key ids match - javascript

I have two datasets and have been trying to combine them, but have no idea where to start. I am making two API calls and below is a small example of a response:
{
early_game_items: {
57: 16
59: 60
106: 1
180: 54
214: 28
232: 6
},
late_game_items: {
108: 1
116: 1
},
mid_game_items: {
1: 52
102: 3
108: 4
116: 1
193: 1
194: 1
223: 1
232: 73
}
}
The other data set is numbered from 1 - 300ish and is an object made of other objects. Below is an snippet:
const items = [{
"id": 57,
"name": "void_stone",
"cost": 825,
"secret_shop": 1,
"side_shop": 0,
"recipe": 0,
"localized_name": "Void Stone"
},
{
"id": 58,
"name": "mystic_staff",
"cost": 2700,
"secret_shop": 1,
"side_shop": 0,
"recipe": 0,
"localized_name": "Mystic Staff"
},
{
"id": 59,
"name": "energy_booster",
"cost": 900,
"secret_shop": 1,
"side_shop": 0,
"recipe": 0,
"localized_name": "Energy Booster"
}...]
I need to put the data from the second data set into the first by matching the key in the first data set with the id in the second. For example:
{
early_game_items: {
57: {amount: 16, name: 'void_stone', cost: 825}
59: {amount: 60...
106: {amount: 1...
180: {amount: 54...
214: {amount: 28...
232: {amount: 6...
}...
Thank you so much for looking this over! I am new to js and am really trying to learn.

Such as another answer naming the datasets dataset1 & dataset2, and assuming dataset2 is an array of objects. If dataset2 is big array, this answer has better performance:
let result = {};
// key = 'early_game_items', 'mid_game_items', 'late_game_items'
for(let key in dataset1) {
result[key] = {};
for(let id in dataset1[key]) {
result[key][id] = { amount: dataset1[key][id] };
}
}
for(let id in dataset2) {
for(let key in dataset1) {
let _item;
if(_item=result[key][id]){
const { name, cost } = dataset2[id];
_item.name = name;
_item.cost = cost;
}
}
}
console.log(result);

Naming the datasets dataset1 & dataset2, and assuming dataset2 is an array of objects:
let result = {};
// key = 'early_game_items', 'mid_game_items', 'late_game_items'
for(let key in dataset1) {
const itemGroup = dataset1[key];
let _itemGroup = {};
for(let id in itemGroup) {
let _item = { amount: itemGroup[id] };
// find item by id, in second dataset
const item = dataset2.find(i => i.id == id) || {};
// get name & cost via destructuring
const { name, cost } = item;
_item.name = name;
_item.cost = cost;
// store in new itemGroup
_itemGroup[id] = _item;
}
// store in result
result[key] = _itemGroup
}
console.log(result);
If dataset2 is an object with numbers as keys, you'll need to modify the "find by id" function:
// find item by id, in second dataset
const item = Object.values(dataset2).find(i => i.id === id) || {};

Related

Find elements from one array in another one and Sum the Total Price

I am trying to calculate the "total cost" of the presents Array in "Object: presents" for a given name (in this case "Peter) by finding the price of the presents in "Object: prices". If the present is not in the Prices array, the price would be 0.
ie: In the case of Peter the "total cost" of the presents would be 1,001 and in the case of Dana would be 6,800.
The outcome would be an array of prices given the matched presents within the 2 arrays of objects (ie for peter = [1,1000], since his presents are "coffee" and "holidays") so later I calculate the sum inside of it with my reducer function.
I have tried to get the array by filtering the name and then try to find the elements included but my solution only iterates on the first element (coffee) and it returns an undefined array.
Any ideas on why and hints on how to move forward?
I am a beginner coder and would really appreciate some guidance.
Cheers,
const presents = [
{ "name": "peter", "presents": ["coffee", "holidays"], "present": "sock", "score": 10 },
{ "name": "dana", "presents": ["car", "phone"], "present": "sock", "score": 9.25 }
]
const prices = [{"present": "coffee","price": 1}, {"present": "holidays","price": 1000
},{"present": "videogames","price": 40},{"present": "computer","price": 600},{"present": "tattoo","price": 30},{"present": "clothes","price": 80},{"present": "car","price": 6000},{"present": "phone","price": 800},{"present": "motorbike","price": 3500}]
const name = 'peter'
const presentsPrices = []
const filteredName = presents.filter((element)=>element.name===name?element:false).map((element, i)=> element.presents[i].includes(prices[i].present)? presentsPrices.push(prices[i].price):0)
const reducer = (accumulator, currentValue) => accumulator + currentValue;
const sum = presentsPrices.reduce(reducer)
console.log(sum)
You can use .find to get the price of a present. Also, there's no need for .filter and .map since you're searching for one object and then get its presents if exists:
const presents = [
{ "name": "peter", "presents": ["coffee", "holidays"], "present": "sock", "score": 10 },
{ "name": "dana", "presents": ["car", "phone"], "present": "sock", "score": 9.25 }
];
const prices = [
{ "present": "coffee","price": 1 },
{ "present": "holidays","price": 1000 },
{ "present": "videogames","price": 40},
{ "present": "computer","price": 600 },
{ "present": "tattoo","price": 30 },
{ "present": "clothes","price": 80 },
{ "present": "car","price": 6000},
{ "present": "phone","price": 800 },
{ "present": "motorbike","price": 3500 }
];
const name = 'peter';
// get presents of person with this name
const { presents: filteredNamePresents = [] } = presents.find(element => element.name===name) || {};
console.log(`Presents: ${filteredNamePresents}`);
// get prices list of these presents
const presentsPrices = filteredNamePresents.reduce((acc,item) => {
const { price } = prices.find(price => price.present===item) || {};
acc = price ? [...acc, price] : acc;
return acc;
}, []);
console.log(`Prices: ${presentsPrices}`);
// calculate totla sum of the prices
const sum = presentsPrices.reduce((accumulator, currentValue) => accumulator + currentValue);
console.log(`Sum: ${sum}`);
Here's something that can help your code:
const people = {
"peter": ["coffee", "holidays"],
...
};
const presents = {
"coffee": 1,
"holidays": 1000,
...
};
But otherwise than better organization with JSON I can't really help you with your problem.

Merging items of array of object if they have equal keys

Array of objects that I got
[
{
"id": 1,
"price": 100
},
{
"id": 1,
"price": 80
},
{
"id": 2,
"price": 8
},
{
"id": 1,
"price": 85
}
]
Array of objects that I am trying to do
[
{
"id": 1,
"price": 88.33 // AVERAGE VALUE BETWEEN DUPLICATED OBJECTS
},
{
"id": 2,
"price": 8
}
]
I am merging and getting the average price for duplicated objects.
What I have done:
I have tried to use filter() function but I removed the duplicated without merging the prices.
If you want to avoid extra loops and extra properties is not a problem, you can use a getter for each object as follow:
You can use the function Array.prototype.reduce for grouping objects by id and the function Object.values for extracting the grouped values.
The getter price calculates the average when this property is accessed.
Extra properties:
{
count: Integer // count of repeated ids.
sum: Double // total sum of prices
}
const arr = [ { "id": 1, "price": 100 }, { "id": 1, "price": 80 }, { "id": 2, "price": 8 }, { "id": 1, "price": 85 } ],
result = Object.values(arr.reduce((r, {id, price}) => {
let current = (r[id] || (r[id] = {id, sum: 0, count: 0, get price() {
return this.sum / this.count;
}}));
current.sum += price;
current.count++;
return r;
}, {}));
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use .reduce() with an ES6 Map. By using reduce() you can accumulate all objects into a Map, where the key is the id from the object and the value is an accumulated array of price values for the given id. You can then convert the Map back into an array using Array.from(), where you can provide a mapping function to convert the [key, value] pairs from the map into an object. The object's price key will be the sum of all numbers in the value array (arr) divided by the length of the array, which will give you the average.
See example below:
const arr = [ { "id": 1, "price": 100 }, { "id": 1, "price": 80 }, { "id": 2, "price": 8 }, { "id": 1, "price": 85 } ];
const res = Array.from(arr.reduce((m, {id, price}) => {
return m.set(id, [...(m.get(id) || []), price]);
}, new Map), ([id, arr]) => ({id, price: arr.reduce((t, n) => t+n, 0) / arr.length}));
console.log(res);
Use forEach loop and build an object with keys as id and aggregate price.
Use Object.values of above object and calculate the averages.
const data = [
{
id: 1,
price: 100,
},
{
id: 1,
price: 80,
},
{
id: 2,
price: 8,
},
{
id: 1,
price: 85,
},
];
const process = (arr) => {
const res = {};
arr.forEach(({ id, price }) => {
res[id] ??= { id, sum: 0, count: 0 };
res[id].sum += price;
res[id].count += 1;
});
return Object.values(res).map(({ id, sum, count }) => ({
id,
price: sum / count,
}));
};
console.log(process(data));

I want to set rank to array value?

I tried to create new array object from array , set rank according to its value . If value is the same, set the same rank and if next value is different set rank by skipping same rank length .
Expected result is
[
{
"rank": 1,
"data": 45
},
{
"rank": 2,
"data": 33
},
{
"rank": 3,
"data": 8
},
{
"rank": 4,
"data": 5
},
{
"rank": 4,
"data": 5
},
{
"rank": 6,
"data": 2
}
]
var data = [8,5,2,33,5,45];
var rankList = [];
var uniqueList = [];
var rank = 0;
var sameRank = 0;
data.sort(function(a,b) { return b - a; });
for(var i in data) {
if(uniqueList.includes(data[i])) {
rank++;
rankList.push({rank: sameRank, data: data[i]});
continue;
}
rank++;
sameRank++;
rankList.push({rank: rank, data: data[i]});
}
console.log(rankList);
Once you've sorted the array, create another array of objects with .map, keeping track of the last rank and data used. If the new data is the same, use the same rank (the one taken from a prior iteration) - otherwise, use the current iteration index plus 1:
const data = [8, 5, 2, 33, 5, 45];
data.sort((a, b) => b - a);
let lastRank = 0;
let lastData;
const output = data.map((data, i) => {
const objToReturn = { data };
objToReturn.rank = data === lastData ? lastRank : i + 1;
lastData = data;
lastRank = objToReturn.rank;
return objToReturn;
});
console.log(output);

Change the structure of my array [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'd like to change the structure of my result.There are objects "itemGroup" and I'd like to delete them and keep keys "fruit" and "vegetable".
[{"id": 1, "shop": "shop1", "itemGroup": {"fruit": 2, "vegetable": 2},"total":4},
{"id": 2, "shop": "shop2", "itemGroup": {"fruit": 0, "vegetable": 1},"total":1}]
I'd like this result
[
{ "id": 1, "shop": "shop1", "fruit": 2, "vegetable": 2, "total": 4 },
{ "id": 2, "shop": "shop2" "fruit": 0, "vegetable": 1, "total": 1 }
]
my code
var myArray = [
{shop: "shop1",item1: "my apple 1",item2: "my carrot 1"},
{shop: "shop1",item1: "my apple 1",item2: "my carrot 1"},
{shop: "shop2",item1: "my apple 0",item2: "my carrot 0"},
{shop: "shop2",item1: "my apple 0",item2: "my carrot 1"}
];
var MyArrayDefinition = [
{item: "my apple 0",color: "red", group: "fruit",score: 0},
{item: "my carrot 1",color: "orange",group: "vegetable",score: 1},
{item: "my apple 1",color: "red", group: "fruit",score: 1},
{item: "my carrot 0",color: "orange",group: "vegetable",score: 0}
];
var k = Object.keys,
items = MyArrayDefinition.reduce((o, v) => (o[v.item] = v, o), {});
var shops = myArray.reduce((o, v, i, s) => (
s = v[k(v).find(k => k)],
s = o[s] || (o[s] = {
fruit: 0,
vegetable: 0,
}),
k(v).forEach(k => k.includes('item') &&
(s[(i = items[v[k]]).group] += i.score)), o), {});
var result = k(shops).map((k, i) => ({
id: i + 1,
shop: k,
itemGroup: shops[k],
total:Object.values(shops[k]).reduce((a, b) => a + b),
}));
Pretty much like in most of your questions from the last couple of days. :-)
You can map over the data, use Object.assign and delete the itemGroup.
let x = f.map(e => {
e = Object.assign(e, e.itemGroup);
delete e.itemGroup;
return e;
})
console.log(x);
<script>
let f = [{
"id": 1,
"shop": "shop1",
"itemGroup": {
"fruit": 2,
"vegetable": 2
},
"total": 4
},
{
"id": 2,
"shop": "shop2",
"itemGroup": {
"fruit": 0,
"vegetable": 1
},
"total": 1
}
]
</script>
Expounding on your "original question" set the percentages of each item in the store, and answering your "modified question" change the structure of my array, this gives you both by modifying your original code.
let myArray = [{"shop":"shop1","item1":"my apple 1","item2":"my carrot 1"},{"shop":"shop1","item1":"my apple 1","item2":"my carrot 1"},{"shop":"shop2","item1":"my apple 0","item2":"my carrot 0"},{"shop":"shop2","item1":"my apple 0","item2":"my carrot 1"}]
let MyArrayDefinition = [{"item":"my apple 0","color":"red","group":"fruit","score":0},{"item":"my carrot 1","color":"orange","group":"vegetable","score": null},{"item":"my apple 1","color":"red","group":"fruit","score":1},{"item":"my carrot 0","color":"orange","group":"vegetable","score":0}]
let k = Object.keys
let items = MyArrayDefinition.reduce((o, v) => (o[v.item] = v, o), {})
let shops = myArray.reduce(function (o, v, i, s) {
return s = v[k(v).find(function (k) {
return k;
})], s = o[s] || (o[s] = {
fruit: 0,
vegetable: 0
}), k(v).forEach(function (k) {
return k.includes('item') && (s[(i = items[v[k]]).group] += i.score);
}), o;
}, {});
// Helper function that calculates percentage
function percentage (amount, total) {
if (total === 0) { // added check for 0 divisor
return `0%`
}
return `${(amount / total) * 100}%`
}
let result = k(shops).map((k, i) => {
let total = Object.values(shops[k]).reduce((a, b) => a + b) | 0 // added check if number else 0
let fruit = shops[k].fruit | 0 // added check if number else 0
let veg = shops[k].vegetable | 0 // added check if number else 0
return {
id: i + 1,
shop: k,
fruit: fruit,
vegetable: veg,
total: total,
fruitPercentage: percentage(fruit, total),
vegetablePercentage: percentage(veg, total)
}
})
console.log(JSON.stringify(result, null, 2))
/** result from console.log()
*
[
{
"id": 1,
"shop": "shop1",
"fruit": 2,
"vegetable": 2,
"total": 4,
"fruitPercentage": "50%",
"vegetablePercentage": "50%"
},
{
"id": 2,
"shop": "shop2",
"fruit": 2,
"vegetable": 0,
"total": 2,
"fruitPercentage": "100%",
"vegetablePercentage": "0%"
}
]
* */
Using map is the way to transpose the data from one array onto another and run calculations if needed.
// Create a function that takes in your result array
function setPercentage (array) {
// Helper function that calculates percentage
function percentage (amount, total) {
return (amount / total) * 100
}
// Map the results of the input array onto a new array,
// and return the result
return array.map((obj) => {
return {
id: obj.id,
shop: obj.shop,
fruit: percentage(obj.itemGroup.fruit, obj.total),
vegetable: percentage(obj.itemGroup.vegetable, obj.total),
total: obj.total
}
})
}
// pass in the result array from your code...
const shops_by_percentage = setPercentage(result)
console.log(shops_by_percentage)
/** result in the console.log()
*
[
{
'id': 1,
'shop': 'shop1',
'fruit': 50,
'vegetable': 50,
'total': 4
},
{
'id': 2,
'shop': 'shop2',
'fruit': 0,
'vegetable': 100,
'total': 1
}
]
*
* */
Below you can find general solution to your problem.
Using this approach you can create unlimited number of items in your items array as well as unlimited number of groups in your definitions and your code will still work as expected. Lastly your score value acts as weight (when you give some item for example score 2 each occurrence will count as two items).
// Your items
const items = [
{
shop: "shop1",
item1: "my apple 1",
item2: "my carrot 1",
},
{
shop: "shop1",
item1: "my apple 1",
item2: "my carrot 1"
},
{
shop: "shop2",
item1: "my apple 0",
item2: "my carrot 0"
},
{
shop: "shop2",
item1: "my apple 0",
item2: "my carrot 1"
},
];
// Your definitions
const definitions = [
{
item: "my apple 0",
color: "red",
group: "fruit",
score: 0
},
{
item: "my carrot 1",
color: "orange",
group: "vegetable",
score: 1
},
{
item: "my apple 1",
color: "red",
group: "fruit",
score: 1
},
{
item: "my carrot 0",
color: "orange",
group: "vegetable",
score: 0
}
];
function groupShops(items) {
return items.reduce((acc, cur) => {
// Find shop with id of current item in accumulator
const currentShop = acc.find(shop => shop.id === cur.shop);
// Get all shop items
const shopItems = Object.keys(cur)
// Filter shop key as it is shop's ID
.filter(key => key !== 'shop')
// Map keys into values
.map(key => cur[key]);
// If shop already exists in accumulator
if (!!currentShop) {
// Return updated accumulator
return acc
// Remove current shop
.filter(shop => shop !== currentShop)
// And add new copy of current shop with new items to the accumulator
.concat({
id: currentShop.id,
items: currentShop.items.concat(shopItems),
});
}
// If shop doesn't exist in accumulator add it there and return updated accumulator
return acc.concat({
id: cur.shop,
items: shopItems,
});
}, []);
};
function extendItems(shops) {
// Filter items which have score 0 or less
const filterItems = items => items.filter(item => item.score > 0);
// Map though shops
return shops.map(shop => {
// Return updated shop
return {
// Keep shop id
id: shop.id,
// Extend itemIds by the properties stored in the definition and filter them
items: filterItems(shop.items.map(item => definitions.find(definition => definition.item === item))),
}
});
}
function calculateResult(shop, index) {
// Get all available groups
const availableGroups = definitions.reduce((acc, cur) => acc.indexOf(cur.group) > -1 ? acc : acc.concat(cur.group), []);
// Calculate total possible score
const getTotalScore = () => shop.items.reduce((acc, cur) => cur.score + acc, 0);
// Get score of a passed group
const getGroupScore = group => shop.items.reduce((acc, cur) => cur.group === group ? acc + cur.score : acc, 0);
// Loop though each available group and get its score
const resultData = availableGroups.reduce((acc, cur) => {
return {
// Copy data from accumulator
...acc,
// Add new property to the accumulator with a property key {group name} and value {percantage}
[cur]: getGroupScore(cur, shop.items) / getTotalScore(shop.items) * 100,
}
}, {});
// Return result object
return {
// Destruct items of the result object
...resultData,
// Store total items count
total: shop.items.length,
// Store shop id
shop: shop.id,
// Store index
id: index,
}
}
// Groups shops
const groupedShops = groupShops(items);
// Groups shops with extended items
const extendedShops = extendItems(groupedShops);
// You result object
const result = extendedShops.map((shop, index) => calculateResult(shop, ++index));
console.log(result);

How to find inside an array of objects the object that holds the highest value?

I have an array that holds several objects named student, each object student has several properties, one of which is an array named grades.
I need to create a function that loops through the student's array and finds which student object has the highest grade inside its grades array.
At the moment I am able to find the highest score, but was not able to understand how to trace back to which student it belongs to.
Here is a snippet of how the function looks like:
function bestStudent() {
var bestGrade = 0;
var student;
for(i=0; i < studentArr.length; i++) {
var student = studentArr[i];
grades = student.grades;
for(g = 0; g <grades.length; g++){
if(grades[g] > bestGrade) {
bestGrade = grades[g];
}
}
}
}
The general idea is the following: you can first map your array of students with their grades to an array of students and their highest grade in order to make it convenient to work with and avoid multiple find-max-grade calculations, and then find the largest of students' highest grade.
Just an example:
var students = [
{
name: "Student 1",
grades: [ 65, 61, 67, 70 ]
},
{
name: "Student 2",
grades: [ 50, 51, 53, 90 ]
},
{
name: "Student 3",
grades: [ 0, 20, 40, 60 ]
}
];
var highestGrades = students.map(function(stud, ind) {
// return a student's name and his highest grade (1)
return {
name: stud.name,
highestGrade: Math.max.apply(Math, stud.grades) // get a student's highest grade
};
// or return index and use it to access original value: (2)
// return {
// index: ind,
// highestGrade: Math.max.apply(Math, stud.grades)
// };
// or return the whole student: (3)
// return {
// student: stud,
// highestGrade: Math.max.apply(Math, stud.grades)
// };
// or just add 'highestGrade' property to object without modifying
// if it's ok for you to have intermediate properties in your object: (4)
// stud.highestGrade = Math.max.apply(Math, stud.grades);
// return stud;
});
// this can be done in O(n), not in O(N * logN) if required:
var bestStudent = highestGrades.sort(function(a, b) {
return b.highestGrade - a.highestGrade;
})[0]; // sort by highest grade desc and return the first (the best) one
// Here we have bestStudent with his name according to map function:
console.log(bestStudent.name + " has the highest score of " + bestStudent.highestGrade); // (1)
// console.log(students[bestStudent.index].name + " has the highest score of " + bestStudent.highestGrade); // (2)
// console.log(bestStudent.student.name + " has the highest score of " + bestStudent.highestGrade); // (3)
// console.log(bestStudent.name + " has the highest score of " + bestStudent.highestGrade); // (4)
You can rewrite this code so that it returns the whole student as the result, or its index, or its specific properties. You can also just add highestGrade property to original object if it's ok for your objects to have an additional intermediate property. It is up to you, the idea doesn't change :)
This code is pretty long, but it is readable and makes the idea of algorithm clear, it is very important since you are a beginner.
If you and your team are fans of shorter but more complex code, then you can easily rewrite it.
Just something like this:
var students = [
{
name: "Student 1",
grades: [ 65, 61, 67, 70 ]
},
{
name: "Student 2",
grades: [ 50, 51, 53, 90 ]
},
{
name: "Student 3",
grades: [ 0, 20, 40, 60 ]
}
];
var bestStudent = students.map(function(stud) {
stud.highestGrade = Math.max.apply(Math, stud.grades);
return stud;
}).sort(function(a, b) {
return b.highestGrade - a.highestGrade;
})[0];
console.log(bestStudent);
By using the same function, you can store the position or the appropriate field
function bestStudent() {
var bestStudent = {};
bestStudent.bestGrade = 0;
var student;
for(i=0; i < studentArr.length; i++) {
var student = studentArr[i];
grades = student.grades;
for(g = 0; g <grades.length; g++){
if(grades[g] > bestStudent.bestGrade) {
bestStudent.bestGrade = grades[g];
bestStudent.name = studentArr[i].name;
}
}
}
return bestStudent;
}
use lodash.js to make thing easy :)
var students=[{Grades:[1,2,3]},{Grades:[5,4,3]},{Grades:[7,77,4]}];
var studentWithBestGrade=_.map(students,function(student,position){
return [position,_.max(student.Grades)];
});
console.log(studentWithBestGrade) //[[0,3],[1,5],[2,77]]
find it JSFIDDLE
var students = [
{
name: "Student 1",
grades: [
90, 98, 80
],
getMyHighest: function(){
return Math.max.apply( Math, this.grades );
}
},
{
name: "Student 2",
grades: [
75, 85, 79
],
getMyHighest: function(){
return Math.max.apply( Math, this.grades );
}
}
,
{
name: "Student 3",
grades: [
75, 85, 99
],
getMyHighest: function(){
return Math.max.apply( Math, this.grades );
}
}
];
var student = students.sort(function(f, l) {
return l.getMyHighest() - f.getMyHighest();
})[0];
console.log(student);
You could use an array for the students with the best grade, if you have more than one.
Then check if the maxGrade is the same as the bestGrade, then push the actual student to the result set and countinue the for loop.
If maxGrade is greater than bestGrade, store the value an put the actual student in a new array.
function bestStudents(studentArr) {
var bestGrade = 0,
bestStudents = [],
i,
maxGrade;
for (i = 0; i < studentArr.length; i++) {
maxGrade = Math.max.apply(null, studentArr[i].grades);
if (maxGrade === bestGrade) {
bestStudents.push(studentArr[i]);
continue;
}
if (maxGrade > bestGrade) {
bestGrade = maxGrade;
bestStudents = [studentArr[i]];
}
}
return bestStudents;
}
var students = [{ name: "Student 1", grades: [90, 98, 99] }, { name: "Student 2", grades: [75, 85, 79] }, { name: "Student 3", grades: [75, 85, 99] }];
console.log(bestStudents(students));
.as-console-wrapper { max-height: 100% !important; top: 0; }
My solution would be using reduce in JS
Only get one student:
var bestStudent = students.reduce(function(a, student){
return Math.max.apply(null, student.grades) >
Math.max.apply(null, a.grades) ?
student : a;}, students[0]);
console.log('Best student is: ' + bestStudent.name + ' with score: '
+ Math.max.apply(null, bestStudent.grades));
Example: https://jsfiddle.net/ahx8jh5g/
In case, you want to get all students which have best grade, let's store it in an array:
var bestStudents = students.reduce(function(a, student){
var maxGradeStu = Math.max.apply(null, student.grades),
maxGradeCur = a.length > 0 ? Math.max.apply(null, a[0].grades) : 0;
if (maxGradeStu === maxGradeCur) {
return a.concat(student);
}
return maxGradeStu > maxGradeCur ? [student] : a;
}, [])
bestStudents.forEach( bestStudent => console.log('Best student is: ' bestStudent.name + ' with score: '
+ Math.max.apply(null, bestStudent.grades)));
For more detail, you can see reduce here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

Categories

Resources