user2025749
user2025749

Reputation: 281

Sorting array object in javascript

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

Answers (3)

Tom Davies
Tom Davies

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

Nina Scholz
Nina Scholz

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 the compareFunction's nature, this may yield a high overhead. The more work a compareFunction 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

Dilip Belgumpi
Dilip Belgumpi

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

Related Questions