Reputation: 281
I have an array with multiple objects such as this:
var test = [
{size: "85A (UK 42A)"},
{size: "80A (UK 40A)"},
{size: "105F (UK 48F)"},
{size: "95E (UK 46E)"},
{size: "92C (UK 44C)"}
]
I want to order it by the size such that the order becomes as below.
var test = [
{size: "80A (UK 40A)"}
{size: "85A (UK 42A)"},
{size: "92C (UK 44C)"}
{size: "95E (UK 46E)"},
{size: "105F (UK 48F)"}
]
I have used this but this returns me the array below:
function sorting(json_object, key_to_sort_by) {
function sortByKey(a, b) {
var x = a[key_to_sort_by];
var y = b[key_to_sort_by];
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}
json_object.sort(sortByKey);
}
var test = [
{size: "105F (UK 48F)"},
{size: "80A (UK 40A)"}
{size: "85A (UK 42A)"},
{size: "92C (UK 44C)"}
{size: "95E (UK 46E)"}
]
Upvotes: 1
Views: 100
Reputation: 899
By default, sort will sort strings by Unicode code point. You'd want to isolate something numerical to sort by and then turn that into a number and use that for the comparison. Something like this should work...
let sizes = [
{size: "85A (UK 42A)"},
{size: "80A (UK 40A)"},
{size: "105F (UK 48F)"},
{size: "95E (UK 46E)"},
{size: "92C (UK 44C)"},
{size: "80B (UK 40B)"},
];
sizes.sort(function(a, b) {
var sizeA = a.size.split(' ')[0];
var sizeB = b.size.split(' ')[0];
let aInt = parseInt(sizeA);
let bInt = parseInt(sizeB);
// If the same number, we can just compare the strings
// since the numeric characters will be equal.
if (aInt === bInt) {
return sizeA.localeCompare(sizeB);
}
// If not equal, compare the numbers.
return aInt - bInt;
});
// For snippet.
console.log(sizes);
Edit: Assuming that if the numeric component is the same, you'd want to sort by the letter. In this case we just compare the strings.
Upvotes: 1
Reputation: 386786
If you like to sort with the character after the number as well, you could use a regular expression for getting this value, too.
var test = [{ size: "105F (UK 48F)" }, { size: "80A (UK 40A)" }, { size: "85A (UK 2A)" }, { size: "92C (UK 44C)" }, { size: "80B (UK 40B)" }, { size: "80C (UK 40C)" }, { size: "95E (UK 46E)" }];
test.sort(function (a, b) {
function getV(s) { return s.match(/^(\d+)(\w+)/); }
var aa = getV(a.size),
bb = getV(b.size);
return aa[1] - bb[1] || aa[2].localeCompare(bb[2]);
});
console.log(test);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For huge data sets, you could use sorting with map, because
The
compareFunction
can be invoked multiple times per element within the array. Depending on thecompareFunction
's nature, this may yield a high overhead. The more work acompareFunction
does and the more elements there are to sort, the wiser it may be to consider using a map for sorting. The idea is to walk the array once to extract the actual values used for sorting into a temporary array, sort the temporary array and then walk the temporary array to achieve the right order.
// the array to be sorted
var list = [{ size: "105F (UK 48F)" }, { size: "80A (UK 40A)" }, { size: "85A (UK 2A)" }, { size: "92C (UK 44C)" }, { size: "80B (UK 40B)" }, { size: "80C (UK 40C)" }, { size: "95E (UK 46E)" }];
// temporary array holds objects with position and sort-value
var mapped = list.map(function(el, i) {
var temp = el.size.match(/^(\d+)(\w+)/);
return { index: i, number: +temp[1], string: temp[2] || '' };
});
// sorting the mapped array containing the reduced values
mapped.sort(function(a, b) {
return a.number - b.number || a.string.localeCompare(b.string);
});
// container for the resulting order
var result = mapped.map(function(el){
return list[el.index];
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 648
var test = [
{size: "85A (UK 42A)"},
{size: "80A (UK 40A)"},
{size: "105F (UK 48F)"},
{size: "95E (UK 46E)"},
{size: "92C (UK 44C)"}
]
var sorted=test.sort(function(a, b) {
return parseInt(a['size'].split(' ')[0])-parseInt(b['size'].split('(')[0]);
})
console.log(sorted);
Upvotes: 0