1

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)"}
]
user2025749
  • 251
  • 1
  • 2
  • 11

3 Answers3

2

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; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Doesnt the function get called for every pair of elemnts? Doesnt that mean you're recreating `getN` on every iteration? – Jamiec Jun 02 '17 at 09:02
  • right, you yould use sorting with map where the map contains the values for sorting, or just spend a new property to each object, or use a hash table for the values, depending of the size of the array for sorting. for a small set, optimizing is not necessary. – Nina Scholz Jun 02 '17 at 09:06
1

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.

Tom Davies
  • 899
  • 6
  • 20
0

 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);           
Dilip Belgumpi
  • 658
  • 4
  • 13