admin管理员组文章数量:1404922
I want to sort an array of objects with labels, for example
var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}]
and an array of labels as a baseline, for example
var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']
Now I want to sort my first array, so that the objects in it follow the order of labels in the second array labels
.
I know basic sorting mechanism with custom parators like
CustomComparator: function(a, b) {
if (a[0].length > b[0].length) return -1;
if (a[0].length < b[0].length) return 1;
return 0;
}
but I have no idea on how to convert this.
In my research I found this solution on stackoverflow coded in ruby, but I don't know if there is a similar option in javascript.
I appreciate any help, invested quite some time on this.
I want to sort an array of objects with labels, for example
var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}]
and an array of labels as a baseline, for example
var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']
Now I want to sort my first array, so that the objects in it follow the order of labels in the second array labels
.
I know basic sorting mechanism with custom parators like
CustomComparator: function(a, b) {
if (a[0].length > b[0].length) return -1;
if (a[0].length < b[0].length) return 1;
return 0;
}
but I have no idea on how to convert this.
In my research I found this solution on stackoverflow coded in ruby, but I don't know if there is a similar option in javascript.
I appreciate any help, invested quite some time on this.
Share Improve this question asked Oct 29, 2019 at 11:25 MagelanMagelan 1893 silver badges14 bronze badges 2- 1 stackoverflow./q/13304543/10221765 and convert to array of objects. – Jack Bashford Commented Oct 29, 2019 at 11:28
- Nina pointed out a problem with one of the options in my answer which I've fixed just now. Pinging you to let you know because you've accepted my answer and so if you used that option... :-) – T.J. Crowder Commented Oct 29, 2019 at 12:07
4 Answers
Reset to default 3You need to provide priority to values as per second array. here we are building a Map from second array name as key and index as priority. so you can use Map
and default value
and sort
var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}]
var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']
let mapper = new Map(labels.map((v, i) => [v, i + 1]))
let final = arrayToBeSorted.sort((a, b) => {
return (mapper.get(a.label) || Infinity) - (mapper.get(b.label) || Infinity)
})
console.log(final)
There are a couple of approaches:
Using
indexOf
to repeatedly search thelabels
arrayUsing a map so looking up the index of a label is quicker
Here's an example using indexOf
(in ES2015+):
arrayToBeSorted.sort((a, b) => labels.indexOf(a.label) - labels.indexOf(b.label));
Live Copy:
var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}];
var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel'];
arrayToBeSorted.sort((a, b) => labels.indexOf(a.label) - labels.indexOf(b.label));
console.log(arrayToBeSorted);
Note that indexOf
will return -1
if the label doesn't exist in labels
, which will make unknown labels appear at the beginning of the result. If you want them at the end instead, check for -1
and replace it with Infinity
.
Here's an example using a map to speed up finding those indexes (in ES2015+):
const map = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
let aindex = map.get(a.label);
if (aindex === null) {
aindex = -1; // Or Infinity if you want them at the end
}
let bindex = map.get(b.label);
if (bindex === null) {
bindex = -1; // ""
}
return aindex - bindex;
});
Live Copy:
var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}];
var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel'];
const map = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
let aindex = map.get(a.label);
if (aindex === null) {
aindex = -1; // Or Infinity if you want them at the end
}
let bindex = map.get(b.label);
if (bindex === null) {
bindex = -1; // ""
}
return aindex - bindex;
});
console.log(arrayToBeSorted);
That's written for clarity and to avoid looking up the labels more than once in the callback. It can be more concise at the cost of a second label lookup in the map:
const map = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
const aindex = map.has(a.label) ? map.get(a.label) : -1; // Or Infinity if you want them at the end
const bindex = map.has(b.label) ? map.get(b.label) : -1; // "
return aindex - bindex;
});
Live Copy:
var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}];
var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel'];
const map = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
const aindex = map.has(a.label) ? map.get(a.label) : -1; // Or Infinity if you want them at the end
const bindex = map.has(b.label) ? map.get(b.label) : -1; // "
return aindex - bindex;
});
console.log(arrayToBeSorted);
It can even be:
const map = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) =>
(map.has(a.label) ? map.get(a.label) : -1) - (map.has(b.label) ? map.get(b.label) : -1)
);
...but for me that's making life too difficult when debugging, etc.
You can create a custom order and order by it:
var arrayToBeSorted = [
{label: 'firstLabel', value: 123},
{label: 'secondLabel', value: 456},
{label: 'thirdLabel', value: 789}
];
let order = { secondLabel: 1, thirdLabel: 2, fourthLabel: 3, firstLabel: 4 };
arrayToBeSorted.sort((a, b) => {
return order[a.label] - order[b.label];
});
console.log(arrayToBeSorted);
Straight-forward using sort-array.
const sortArray = require('sort-array')
const arrayToBeSorted = [
{label: 'firstLabel', value: 123},
{label: 'secondLabel', value: 456},
{label: 'thirdLabel', value: 789}
]
sortArray(arrayToBeSorted, {
by: 'label',
order: 'labelOrder',
customOrders: {
labelOrder: ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']
}
})
console.log(arrayToBeSorted)
Prints this output:
[
{ label: 'secondLabel', value: 456 },
{ label: 'thirdLabel', value: 789 },
{ label: 'firstLabel', value: 123 }
]
版权声明:本文标题:javascript - How to sort an array of objects with labels according to other array of labels? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744866800a2629392.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论