I have an array of objects like so:
var data = {
a: [
{ keyone:'c', keytwo: 'anna', keythree: 21, keyfour: 15 },
{ keyone:'a', keytwo: 'anna', keythree: 22, keyfour: 15 },
{ keyone:'s', keytwo: 'anna', keythree: 10, keyfour: 15 },
{ keyone:'v', keytwo: 'anna', keythree: 7, keyfour: 15 }
],
b: [
{ keyone:'f', keytwo: 'any', keythree: 45, keyfour: 100 },
{ keyone:'b', keytwo: 'any', keythree: 146, keyfour: 100 },
{ keyone:'t', keytwo: 'any', keythree: 23, keyfour: 100 },
{ keyone:'h', keytwo: 'any', keythree: 11, keyfour: 100 }
]
};
I want to assign ranks to each object, based on values of keythree
and keyfour
, within the groups as well as within the entire data set. How would I do it?
Update: I have depicted the ranks in my code above.
Resultant object:
var data = {
a: [
{ keyone:'c', keytwo: 'anna', keythree: 21, keyfour: 15, rankgroup: 3, rankall: 4 },
{ keyone:'a', keytwo: 'anna', keythree: 22, keyfour: 15, rankgroup: 4, rankall: 5 },
{ keyone:'s', keytwo: 'anna', keythree: 22, keyfour: 15, rankgroup: 2, rankall: 2 },
{ keyone:'v', keytwo: 'anna', keythree: 7, keyfour: 15, rankgroup: 1, rankall: 1 }
],
b: [
{ keyone:'f', keytwo: 'any', keythree: 45, keyfour: 100 },
{ keyone:'b', keytwo: 'any', keythree: 146, keyfour: 100 },
{ keyone:'t', keytwo: 'any', keythree: 23, keyfour: 100 },
{ keyone:'h', keytwo: 'any', keythree: 11, keyfour: 100 }
]
};
I am using lodash
. My idea is to first sort the array based on those keys, then loop over the original object, insert the sorted index by comparing another key. This is what I have tried:
var keys = Object.keys(data);
var result = {};
var numkeys;
for(var i=0; i < keys.length; i++) {
if(!numkeys) {
var numkeys = _.keys(_.pick(data[keys[i]][0], _.isNumber));
}
for(var j=0;j<numkeys.length;j++) {
var sorted = _.sortBy(data['a'], numkeys[j]);
_.forEach(sorted, function(n, k) {
//THIS FAILS
var t = _.set(_.where(data[keys[i]], {keyone: n.keyone}), keys[i]+'rank', k);
console.log(t);
});
}
}
How would I do it? My logic seems too complex and the set
method does not update the original object by key but adds a new entry after the main object.
Update: Notice the duplicate occurrence of 22
for the object a
. This leads to an issue when assigning ranks, since indexOf
will always return the index of the first occurrence, hence the second occurrence will never have an index assigned to it and hence the value will be undefined.
All elements are ranked from 1 to N in ascending order if they are distinct. If there are say x repeated elements of a particular value then each element should be assigned a rank equal to the arithmetic mean of x consecutive ranks.
assign() method to convert an array to an object, e.g. const obj = Object. assign({}, arr) . The Object. assign method takes a target and source objects as parameters, applies the properties from the sources to the target and returns the result.
To sort an array of objects in JavaScript, use the sort() method with a compare function. A compare function helps us to write our logic in the sorting of the array of objects. They allow us to sort arrays of objects by strings, integers, dates, or any other custom property.
Sorting array of objectsArrays of objects can be sorted by comparing the value of one of their properties.
this is how I achieved it.
collect all keythree
into an array and sort them (to assign rankall
based on index
).
var all = [];
_.forEach(data, function (a, key) {
_.forEach(a, function(n, k){
all.push(n.keythree);
});
});
all.sort(function(a,b){
return a-b;
});
assign ranks
_.forEach(data, function (a, key) {
var sorted = _.sortBy(a, 'keythree');
_.forEach(sorted, function(n, k) {
var index = _.findIndex(data[key], {keyone: n.keyone});
data[key][index]['rankgroup'] = k+1;
data[key][index]['rankall'] = all.indexOf(n.keythree)+1;
});
});
check this fiddle
i'm creating another array for dupes
_.forEach(a, function(n, k) {
if (all.indexOf(n.keythree) !== -1) {
dupes.push(n.keythree);
}
all.push(n.keythree);
});
and for getting the global rank for these dupe items
function getGlobalRank(n) {
var val = n.keythree;
if (sorted_dupes[val] === undefined) {
sorted_dupes[val] = [];
_.forEach(data, function(a, key) {
_.forEach(_.where(a, {
keythree: val
}), function(b) {
sorted_dupes[val].push(b);
});
});
sorted_dupes[val] = _.sortByAll(sorted_dupes[val], ['keyfour', 'keytwo', 'keyone']);
}
return _.findIndex(sorted_dupes[val], {
keyone: n.keyone,
keytwo: n.keytwo,
keythree: n.keythree,
keyfour: n.keyfour
}) + 1 + all.indexOf(val);
}
see that the items are sorted based on all the properties in the order keythree
, keyfour
, keytwo
, keyone
(you can change the order inside _.sortByAll
if you want to)
the code looking uglier than i thought. will update the refactored code soon
check the fiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With