So here I have a system that identifies the object with the highest count, however as we can see there are two objects that both have the highest count. What I want to be able to do is take the top counts, however many that may be, and output one at random. How can I do this?
var objects = [
{username: 'mark', count: 3},
{username: 'dave', count: 5},
{username: 'john', count: 5},
{username: 'lucy', count: 2},
];
var res = objects.reduce(function(resObj, obj) {
return resObj.count > obj.count ? resObj : obj
})
console.log(res);
Thanks!
Nice question here is how you can do it
Note: I added a few more of the same counts to show you how this works regardless of how many matches you have:
Working example
var objects = [
{username: 'mark', count: 3},
{username: 'dave', count: 5},
{username: 'john', count: 5},
{username: 'amy', count: 5},
{username: 'adam', count: 5},
{username: 'fenty', count: 5},
{username: 'lucy', count: 2},
];
// make an array to push same counts
var arr = [];
var res = objects.reduce(function(resObj, obj) {
// keep track of (and set) max count
var max = Math.max(resObj.count, obj.count);
// if count is equal push to our array
if (max === obj.count) {
arr.push(obj);
}
// same code as before
return resObj.count >= obj.count ? resObj : obj;
});
// get random index from our array
var randIndex = Math.floor(Math.random() * arr.length);
// get random result from our objects that have the same count:
console.log(arr[randIndex]);
Here is the answer using simple for loops. Returns random heightest object
function getHighest(objects) {
var highest = 0;
var heighestArr = [];
// first get highest index
for(var i=1; i<objects .length;i++){
if(objects[i].count > objects[highest].count){
highest= i;
}
}
// then add all the highest ones in an array
for(var i=0; i<objects .length;i++){
if(objects[i].count === objects[highest].count){
heighestArr.push(objects[i])
}
}
// return random from that array
return heighestArr[Math.floor(Math.random()*heighestArr.length)];
}
var objects = [
{username: 'mark', count: 3},
{username: 'dave', count: 5},
{username: 'john', count: 5},
{username: 'lucy', count: 2},
];
var res = objects.slice(1).reduce(function(resObj, obj) {
if (resObj[0].count > obj.count) {
return resObj;
} else if (resObj[0].count === obj.count) {
return [...resObj, obj];
} else {
return [obj]
}
}, [objects[0]])
var randomElement = function(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
console.log(randomElement(res));
Untested but this is the basic idea.
Related
I've been stuck on this problem for hours, I can't seem to add the scores together and msot of the things I've tried end up giving me NaN or entirely wrong scores.
Example input is:
Example 1:
let ppl = [{name: "Anthony", score: 10},
{name: "Fred", score : 10},
{name: "Anthony", score: -8},
{name: "Winnie", score: 12}];
My code which is not adding the scores together for multiple entries.
function countScores(people) {
// Your code here
let scoreCount = {};
people.forEach(person => { // Go through the people
let name = person.name; // Grab the name of the person
let score = person.score // Grab the score of the person
if (scoreCount[name]) { //Check if name exists already and add scores together
scoreCount[score] += person.score;
console.log("Am I being accessed???")
}
score = Number(person.score); // Grab the score of person and set it to score
name = person.name; // Grab the name of the person
console.log(name, score);
scoreCount[name] = score;
})
console.log(scoreCount)
console.log("Endig Calculation of Scores....")
return scoreCount;
};
My results are:
+ expected - actual
{
- "Anthony": -8
+ "Anthony": 2
"Fred": 10
"Winnie": 12
}
Check the below implementation using reduce()
let ppl = [{name: "Anthony", score: 10},
{name: "Fred", score : 10},
{name: "Anthony", score: -8},
{name: "Winnie", score: 12}];
function countScores(people) {
let result = people.reduce((res, record) => {
if(!res[record.name]) {
res[record.name] = record.score;
}else {
res[record.name] += record.score;
}
return res;
}, {});
return result;
}
console.log(countScores(ppl));
You can use reduce() to do it
let data = [{name: "Anthony", score: 10},
{name: "Fred", score : 10},
{name: "Anthony", score: -8},
{name: "Winnie", score: 12}];
let result = data.reduce((a,v) =>{
let exists = a[v.name]
if(exists){
a[v.name] += v.score
}else{
a[v.name] = v.score
}
return a
},{})
console.log(result)
i have to make a object from array then i can work with it letter.
i am trying this code it work's but output getting only last one
let datas = "team1 1, team2 2, team3 3";
let teamdata = datas.split(" ");
var myObj = (function () {
var result = { Tname: null, count: null };
datas.split(/\s*\,\s*/).forEach(function (el) {
var parts = el.split(/\s* \s*/);
result.Tname = parts[0];
result.count = parseInt(parts[1]);
});
return result;
})();
console.log(myObj);
output getting { Tname: 'team3', count: 3 }
need output
[{name: "team1", count: 1},
{name: "team2", count: 2},
{name: "team3", count: 3}]
Simply, You could do it with
String.split() and Array.map()
let datas = "team1 1, team2 2, team3 3";
let teamdata = datas.split(", "); // ['team1 1', 'team2 2', 'team3 3']
let result = teamdata.map(team=>({team:team.split(/\s+/)[0],count:+team.split(/\s+/)[1]}))
console.log(result);
expected output:
[{name: "team1", count: 1},
{name: "team2", count: 2},
{name: "team3", count: 3}]
i have to make a object
But you then claim that your expected output is an array, not an object:
[
{name: "team1", count: 1},
{name: "team2", count: 2},
{name: "team3", count: 3}
]
In that case, make an array and then .push() to that array within the loop:
var result = [];
datas.split(/\s*\,\s*/).forEach(function (el) {
var parts = el.split(/\s* \s*/);
result.push({
Tname: parts[0],
count: parseInt(parts[1])
});
});
return result;
This should work fine:
let datas = "team1 1, team2 2, team3 3";
var results = [];
var myObj = (function () {
var result = { Tname: null, count: null };
datas.split(/\s*\,\s*/).forEach(function (el) {
var parts = el.split(/\s* \s*/);
result.Tname = parts[0];
result.count = parseInt(parts[1]);
results.push(result);
});
return results;
})();
console.log(results)
The problem with your code was that you successfully splitted the string and converted it to the object but as you are expecting the result to be in the array you were not storing the object rather were rewriting the same object time and again.
I am new to JavaScript and while learning it trying to filter an employee based on education but my filter is returning a null value. Can anyone help me understand why is this so?
var employeeEdu = [{education: 'Masters'}];
var employees = [{id: 1, age: 35, name: 'James', dept: 'IT', education: 'Masters'},
{id: 2, age: 25, name: 'David', dept: 'Accounts', education: 'High School'},
{id: 3, age: 45,name: 'Tim', dept: 'HR', education: 'Graduate'},
{id: 4, age: 50,name: 'Vinod', dept: 'IT', education: 'PHD'}];
function chooseQualified(arrEmployee, empEducation) {
return arrEmployee.filter(function(emp) {
return emp.education === empEducation.education;
// return emp.education === 'Masters';
});
}
console.log(chooseQualified(employees, employeeEdu));
It's because employeeEdu is an array, and employeeEdu.education is undefined. What you need to do is to checkout employeeEdu[0].education:
var employeeEdu = [{education: 'Masters'}];
var employees = [{"id":1,"age":35,"name":"James","dept":"IT","education":"Masters"},{"id":2,"age":25,"name":"David","dept":"Accounts","education":"High School"},{"id":3,"age":45,"name":"Tim","dept":"HR","education":"Graduate"},{"id":4,"age":50,"name":"Vinod","dept":"IT","education":"PHD"}];
function chooseQualified(arrEmployee, empEducation) {
return arrEmployee.filter(function(emp) {
return emp.education === empEducation[0].education;
// return emp.education === 'Masters';
});
}
console.log(chooseQualified(employees, employeeEdu));
Another solution is to remove the wrapping array:
employeeEdu = {education: 'Masters'};
Like #Ori Drori says, employeeEdu is an array, so empEducation.education is undefined, but empEducation[0].education is 'Masters'. I suggest that employeeEdu be a object instead of array, like below code. var employeeEdu = {education: 'Masters'};
var employeeEdu = {education: 'Masters'};
var employees = [{id: 1, age: 35, name: 'James', dept: 'IT', education: 'Masters'},
{id: 2, age: 25, name: 'David', dept: 'Accounts', education: 'High School'},
{id: 3, age: 45,name: 'Tim', dept: 'HR', education: 'Graduate'},
{id: 4, age: 50,name: 'Vinod', dept: 'IT', education: 'PHD'}];
function chooseQualified(arrEmployee, empEducation) {
return arrEmployee.filter(function(emp) {
return emp.education === empEducation.education;
// return emp.education === 'Masters';
});
}
console.log(chooseQualified(employees, employeeEdu));
/* #Params:
* array0 [Array of Objects]: Array to search through.
* array1 [Array of Objects]: Array with the key/value to search for.
* key [String]: Key of the object in array1.
* index [Number](optional): Index of array1. default: 0.
*/
// Returns a new array of objects witch matched by key/value from the two given arrays.
function findByKV(array0, array1, key, index = 0) {
// Get the value of the key to be searched for
var value = array1[index][key];
// Filter the array to be searched obj is each Object in array1
filter()
array0.filter(function(obj) {
// Get each obj key of array0 and ...
Object.keys() .some()
return Object.keys(obj).some(function(key) {
// ...return true if at least one String value matches the value of the key in array1
.toString() .indexOf()
return obj[key].toString().indexOf(value) != -1;
var target0 = [{education: 'Masters'}];
var target1 = [{dept: 'IT',education: ''}];
var employees = [
{id: 1,age: 35,name: 'James',dept: 'IT',education: 'Masters'},
{id: 2,age: 25,name: 'David',dept: 'Accounts',education: 'High School'},
{id: 3,age: 45,name: 'Tim',dept: 'HR',education: 'Graduate'},
{id: 4,age: 50,name: 'Vinod',dept: 'IT',education: 'PHD'},
{id: 5,age: 46,name: 'Matt',dept: 'IT',education: 'Masters'}
];
function findByKV(array0, array1, key, index = 0) {
var value = array1[index][key];
var array2 = array0.filter(function(obj) {
return Object.keys(obj).some(function(key) {
return obj[key].toString().indexOf(value) != -1;
});
});
return array2;
}
var result0 = findByKV(employees, target0, 'education');
var result1 = findByKV(employees, target1, 'dept');
console.log('Found targrt0: ' + JSON.stringify(result0, null, 2));
console.log('Found target1: ' + JSON.stringify(result1, null, 2));
I have searched stackoverflow for answers but I do not really see anything which solves this. I want to take an objects in an array, match them by their name. Then calculate the total of the matching objects hours value.
If this is the array
var arr = [{name: 'Apple', hours: 6}, {name: 'Nokia', hours: 8},
{name: 'Apple', hours: 4}, {name: 'Nokia', hours: 12},];
//return [{name: 'Apple', totalHrs: '10'}], [{name: 'Nokia', totalHrs:
'24'}]
Thank you for any help.
That's not possible, an object literal can't have two identical keys. Instead you could sum the values and take the name as a key
let arr = [{name: 'Apple',hours: 6}, {name: 'Nokia',hours: 8},{name: 'Apple',hours: 4}, {name: 'Nokia',hours: 12}];
let obj = arr.reduce((a, b) => {
a[b.name]= (a[b.name] || 0) + b.hours;
return a;
}, {});
console.log(obj);
Use some hashing
and for loop
var hash={}; // hash array to contain names and total hours
var arr = [{name: 'Apple', hours: 6}, {name: 'Nokia', hours: 8},
{name: 'Apple', hours: 4}, {name: 'Nokia', hours: 12},];
for(var i=0; i<arr.length; i++)
{
if(arr[i].name in hash)
hash[arr[i].name]+=arr[i].hours;
else
hash[arr[i].name]=arr[i].hours;
}
console.log(hash);`
You can do this:
function findItemsByProp(array, propName, value) {
var results = [];
for (var i = 0; i < array.length; i++) {
if (array[i][propName] == value)
results.push(array[i]);
}
return results;
}
This is how to use it:
var matching = findItemsByProp(myArray, 'name', 'someValueOfNameProp');
var total = 0;
for(var i = 0; i < matching.length; i++)
total += matching[i].hours;
console.log(total);
of course you can do the sum while iterating over the array, but this is a general method to be used any where else.
So, I have something like this:
objArray1 = [ { candidate1: "Alex" , votes: 4}, { candidate2: "Paul", votes: 3}];
objArray2 = [ { candidate1: "Alex" , votes: 7}, { candidate2: "Ben", votes: 3}, { candidate3: "Melisa", votes:8 }];
I am trying to use javascript to make an array with all the candidates and see how many votes each of them have. The part to calculate the votes is easy, but I don't know how to put all the candidates in one array.
I should get an array with: Alex, Paul, Ben and Melisa.
Thank you!
You could use a hashtable and group by name.
var array1 = [ { candidate1: "Alex" , votes: 4}, { candidate2: "Paul", votes: 3}],
array2 = [ { candidate1: "Alex" , votes: 7}, { candidate2: "Ben", votes: 3}, { candidate3: "Melisa", votes:8 }],
grouped = [array1, array2].reduce(function (hash) {
return function (r, a) {
a.forEach(function (o, i) {
var name = o['candidate' + (i + 1)];
if (!hash[name]) {
hash[name] = { candidate: name, votes: 0 };
r.push(hash[name]);
}
hash[name].votes += o.votes;
});
return r;
};
}(Object.create(null)), []);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
var candidates = [];
var found = 0;
for(var i=0;objArray1.length>i;i++){
found = 0;
//add votes to candidate array
for(var j=0;candidates.length>j;j++){
if(candidates[j].name==objArray1[i][Object.keys(objArray1[i])[0]]){
candidates[j].votes = candidates[j].votes+objArray1[i].votes;
found = 1;
}
}
//if condidate not found in votes array, create new
if(found==0){
var tmp = {};
tmp.name = objArray1[i].candidate;
tmp.votes = objArray1[i].votes;
//add to array
candidates.push(tmp);
}
}
console.log(candidates);
Generate an object which holds property name as name and vote count as value.
var objArray1 = [ { candidate1: "Alex" , votes: 4}, { candidate2: "Paul", votes: 3}], objArray2 = [ { candidate1: "Alex" , votes: 7}, { candidate2: "Ben", votes: 3}, { candidate3: "Melisa", votes:8 }];
var res = []
// cobine two arrays
.concat(objArray1, objArray2)
// iterate over the arrays
.reduce(function(obj, o) {
// get the key except the votes
var key = Object.keys(o).find(function(k) {
return k != 'votes';
})
// define property if not already defined
obj[key] = obj[key] || 0;
// add the vote count
obj[key] += o.votes;
// return object refernece
return obj;
// set initial value as empty object
}, {});
console.log(res);
// get the names array if need
console.log(Object.keys(res));
Short solution using Array.prototype.concat(), Array.prototype.reduce() and Array.prototype.map() functions:
var objArray1 = [ { candidate1: "Alex" , votes: 4}, { candidate2: "Paul", votes: 3}],
objArray2 = [ { candidate1: "Alex" , votes: 7}, { candidate2: "Ben", votes: 3}, { candidate3: "Melisa", votes:8 }],
grouped = objArray1.concat(objArray2).reduce(function(r, o){
var k = Object.keys(o).filter(function(k){
return k.indexOf('candidate') === 0;
})[0];
(r[o[k]])? r[o[k]].votes += o.votes : r[o[k]] = {candidate: o[k], votes: o.votes};
return r;
}, {}),
result = Object.keys(grouped).map(function(k){ return grouped[k]; });
console.log(result);
To get the list of names as you asked
var rawArrays = objArray1.concat(objArray2), Candidates = [], tmp = []
for (var i in rawArrays) {
tmp[rawArrays[i][Object.keys(rawArrays[i])[0]]] = 1
}
Candidates = Object.keys(tmp)
To get array with candidates and votes sum
var rawArrays = objArray1.concat(objArray2), Candidates = []
for (var i in rawArrays) {
name = rawArrays[i][Object.keys(rawArrays[i])[0]]
if (Candidates[name]) Candidates[name] += rawArrays[i].votes
else Candidates[name] = rawArrays[i].votes
}