Reputation: 31
I have the following data:
Data = [
{ "rock": "granite", "youngerThan": "schist"},
{ "rock": "basalt", "youngerThan": null},
{ "rock": "Picrite", "youngerThan": "granite"},
{ "rock": "schist", "youngerThan": "basalt"}
]
etc and I would like to get a sorted array for rock
based on attribute youngerThan
. Note that youngerThan
can be undefined which means this rock is the oldest (at the bottom).
Thus what I want to obtain is the following list: (oldest to youngest)
basalt, schist, granite, picrite
youngest to oldest
picrite,granite, schist, basalt
Upvotes: 3
Views: 10769
Reputation: 386624
At least you need to sort the data by the given relation with a tree and then get a sorted result by traversing the tree.
var data = [{ rock: "granite", youngerThan: "schist" }, { rock: "basalt", youngerThan: null }, { rock: "Picrite", youngerThan: "granite" }, { rock: "schist", youngerThan: "basalt" }],
tree = function (data, root) {
var r = [], o = {};
data.forEach(function (a) {
o[a.rock] = { data: a, children: o[a.rock] && o[a.rock].children };
if (a.youngerThan === root) {
r.push(o[a.rock]);
} else {
o[a.youngerThan] = o[a.youngerThan] || {};
o[a.youngerThan].children = o[a.youngerThan].children || [];
o[a.youngerThan].children.push(o[a.rock]);
}
});
return r;
}(data, null),
sorted = tree.reduce(function traverse(r, a) {
return r.concat(a.data, (a.children || []).reduce(traverse, []));
}, [])
console.log(sorted);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 18381
// Case sensitivity
var data = [ { "rock": "granite", "youngerThan": "schist"},{ "rock": "schist", "youngerThan": "basalt"},{ "rock": "basalt" },{ "rock": "granite", "youngerThan": "Picrite"}]
data.sort((a,b) =>{
if(!a.youngerThan || a.youngerThan < b.youngerThan){
return -1
}else if (!b.youngerThan || a.youngerThan > b.youngerThan){
return 1
}
return 0
})
console.log(data);
// Case insensitivity
var data = [ { "rock": "granite", "youngerThan": "schist"},{ "rock": "schist", "youngerThan": "basalt"},{ "rock": "basalt" },{ "rock": "granite", "youngerThan": "Picrite"}]
data.sort((a,b) =>{
var nameA = a.youngerThan ? a.youngerThan.toUpperCase() : null ; // ignore upper and lowercase
var nameB = b.youngerThan ? b.youngerThan.toUpperCase() : null ; // ignore upper and lowercase
if(!nameA || nameA < nameB){
return -1;
}else if (!nameB || nameA > nameB){
return 1;
}
return 0;
})
console.log(data);
Upvotes: 2
Reputation: 504
The sort function in javascript can take an optional comparator as an argument to sort in a defined order for complex objects like the one you have. I didn't understand fully what you wanted but something like this can be done. I mean you can modify this custom function here to sort the object according to your own preferences.
More info here
function compare(obj1,obj2){
if(obj1.youngerThan === null)
return -1;
else
return 1;
}
var Data = [
{ "rock": "granite", "youngerThan": "schist"},
{ "rock": "schist", "youngerThan": "basalt"},
{ "rock": "basalt", "youngerThan": null},
{ "rock": "granite", "youngerThan": "picrite"}
];
Data.sort(compare);
console.log(Data);
/*
[ { rock: 'basalt', youngerThan: null },
{ rock: 'granite', youngerThan: 'picrite' },
{ rock: 'schist', youngerThan: 'basalt' },
{ rock: 'granite', youngerThan: 'schist' } ]
*/
Upvotes: 0