Reputation: 7121
Consider this:
[{name:'John'},{age:25},{address:'some street'}]
As you can see none of the keys are a consistent name, so I cannot use.
arr.sort((a,b)=> a.consistentKey < b.consistentKey);
How can I go about sorting something like this, by name, and by value?
so the following sorted by key in alphabetical order should be:
[{address:'some street'},{age:25},{name:'John'}]
Upvotes: 3
Views: 2665
Reputation: 1278
Below is the solution I would use. This solution provides a keys only sort, a values only sort, a keys then values sort, and a values then keys sort.
class FunkySort {
sort (sortType) {
switch (sortType) {
case 'keysOnly':
return data => this._sortByKey(data);
case 'valuesOnly':
return data => this._sortByValue(data);
case 'valuesPrimary':
return data => {
data = this._sortByKey(data);
return this._sortByValue(data);
};
case 'keysPrimary':
return data => {
data = this._sortByValue(data);
return this._sortByKey(data);
};
}
}
_sortByKey (data) {
return data.sort((a, b) => {
var keyA = Object.keys(a)[0];
var keyB = Object.keys(b)[0];
return keyA < keyB ? -1 : keyA > keyB ? 1 : 0;
});
}
_sortByValue (data) {
return data.sort((a, b) => {
// note that in Node >=v7 you could use `Object.values()`, but not in <v7.0
var valueA = a[Object.keys(a)[0]];
var valueB = b[Object.keys(b)[0]];
return valueA < valueB ? -1 : valueA > valueB ? 1 : 0;
});
}
}
const dataArr = [{name:'John'},{age:25},{address:'some street'}];
const fs = new FunkySort();
fs.sort('keysPrimary')(dataArr);
Note that fs.sort
is a curried function. The first call sets the type of sort to be done, so fs.sort('keysPrimary')
returns a function that takes an array of objects and sorts it first by the values, and then by the keys, resulting in an array of objects sorted by key, and if there are multiple objects with the same key, those are sorted by value.
If you don't need this level of flexibility in the type of sort, then just the _sortByKey
helper method should suffice.
Upvotes: 0
Reputation:
You can do this with
input.sort((a, b) => {
const keya = Object.keys(a)[0];
const keyb = Object.keys(b)[0];
return keya.localeCompare(keyb) || a[keya].localeCompare(b[keyb]);
});
Using localeCompare
is both shorter and more robust in the face of different language locales.
Upvotes: 0
Reputation: 4329
If you are thinking of sorting on the basis of key first and then further on values, you can try the following :
var a = [{name:'John'},{age:25},{address:'some street'}];
alert(JSON.stringify(a.sort((a, b) => {
nameA = Object.keys(a)[0];
nameB = Object.keys(b)[0];
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
})));
Here I have considered only one key, but you can always extend it to multiple keys and similarly you can further sort on the basis of values too.
Upvotes: 1
Reputation: 33605
If you extract the key name using Object.keys
, then you can get the values you need to perform the comparison:
[{name: 'John'}, {age: 25}, {address:'some street'}].sort((a, b) => {
const keyA = Object.keys(a)[0]
const valA = a[keyA]
const keyB = Object.keys(b)[0]
const valB = a[keyB]
if (keyA > keyB) {
return 1
} else if (keyA < keyB) {
return -1
} else /* equal */ {
if (valA > valB) {
return 1
} else if (valA < valB) {
return -1
} else /* equal */ {
return 0
}
}
})
Upvotes: 0