1

I have an array of objects in that I want to sort the array based on the xxx version number string. But it seems there is an issue in sorting the order as per my desire.

I have seen the existing solutions for example, the Existing Question Suggested by community. But it dealt with plain arrays instead of array of objects. I can tweak the answer as per needs. But the solutions seems to be pretty long. So I'm looking for a much simpler solutions.

Example Object:

my_list = [{"xxx": "9.6", "no_of_occurrence": 1 }, {"xxx": "9.2", "no_of_occurrence": 1},
{"xxx": "9.11", "no_of_occurrence": 1}, {"xxx": "9.10", "no_of_occurrence": 1}]

After sorting My desired output should be

Either

[{"xxx": "9.11", "no_of_occurrence": 1 }, {"xxx": "9.10", "no_of_occurrence": 1},
{"xxx": "9.6", "no_of_occurrence": 1}, {"xxx": "9.2", "no_of_occurrence": 1}]

or

[{"xxx": "9.2", "no_of_occurrence": 1 }, {"xxx": "9.6", "no_of_occurrence": 1},
{"xxx": "9.10", "no_of_occurrence": 1}, {"xxx": "9.11", "no_of_occurrence": 1}]

To achieve this I'm facing some issues. The decimal places are not treated the way they should be.

What I've tried so far is:

Approach 1:

my_list.sort((a, b) => 
     {
       if (a['xxx'] < b['xxx']) {
         return -1;
       }
       if (a['xxx'] > b['xxx']) {
         return 1;
       }
       return 0;
     }
  );

Approach 2:

my_list.sort((a, b) => {a['xxx'] - b['xxx']});

I did tried converting the string to float by using the "parseFloat(a['xxx'])" and "parseFloat(a['xxx']).toFixed(2)" as well. But nothing seems to be working.

The output generated by the above sort functions is:

[{
 no_of_occurrence: 1,
 xxx: "9.6"
}, {
 no_of_occurrence: 1,
 xxx: "9.2"
}, {
 no_of_occurrence: 1,
 xxx: "9.11"
}, {
 no_of_occurrence: 1,
 xxx: "9.10"
}]

However I tried, I'm not able to achieve what I desired. How can I treat the 9.10 is greater than 9.2? I know javascript treats 9.10 as 9.1 vise versa. But the data I received from the client and the client expectation is 9.10 is > 9.2.

Your help is appreciated.

6
  • 2
    This answer on how to sort version numbers might help Commented Jun 14, 2022 at 11:27
  • Are these regular floating point numbers (where 9.6 > 9.11) or are they version numbers (where 9.11 > 9.6)? Your desired ordering suggests the latter. Commented Jun 14, 2022 at 11:31
  • @jarmod: These are version numbers. That means 9.10 is greater than 9.6 Commented Jun 14, 2022 at 11:45
  • 1
    That's critical context. I've modified the question to clarify. Commented Jun 14, 2022 at 11:53
  • Does this answer your question? Sort version-dotted number strings in Javascript? Commented Jun 14, 2022 at 11:54

5 Answers 5

3

Or simply do this:

const my_list = [{"xxx": "9.6", "no_of_occurrence": 1 }, {"xxx": "9.2", "no_of_occurrence": 1},
{"xxx": "9.11", "no_of_occurrence": 1}, {"xxx": "9.10", "no_of_occurrence": 1}];

console.log(my_list.sort((a,b)=>{a=a.xxx.split(".");b=b.xxx.split(".");
 return a[0]-b[0] || a[1]-b[1];}));

Sign up to request clarification or add additional context in comments.

Comments

2

The Prana solution was close, but it is not sufficient one. Based on the order you are not comparing float, because 9.10 < 9.11 < 9.2 < 9.6, but that is not order you want.

Its more like chapters and subchapters, then you need to compare the chapter part first, and subchapter part later.

const my_list = [{"xxx": "10.6", "no_of_occurrence": 1 }, {"xxx": "9.2", "no_of_occurrence": 1},
{"xxx": "9.11", "no_of_occurrence": 1}, {"xxx": "9.10", "no_of_occurrence": 1}]

const sorted = my_list.sort((a, b) => {
       const _a = Number(a['xxx'].split('.')[0])
       const _b = Number(b['xxx'].split('.')[0])
       if (_a < _b) {
         return -1;
       }
       if (_a > _b) {
         return 1;
       }
       
       const _aa = Number(a['xxx'].split('.')[1])
       const _bb = Number(b['xxx'].split('.')[1])

       if (_aa < _bb) {
         return -1;
       }
       if (_aa > _bb) {
         return 1;
       }

       return 0;
     });
     
console.log(sorted);

1 Comment

Thanks @liblik. This worked. It worked even for the numbers like ".31" and "15" as well.
2

How can I treat the 9.10 is greater than 9.2?

Here you are not considering them as regular floating values. So if you ignore the ., you can easily compare them.

Try this one

my_list.sort((a, b) => {
       const _a = a['xxx'].split('.')
       const _b = b['xxx'].split('.')
       if (Number(_a[0]) < Number(_b[0])) {
         return -1;
       }
       if (Number(_a[0]) > Number(_b[0])) {
         return 1;
       }
       if (Number(_a[1]) < Number(_b[1])) {
          return -1;
       }
       if (Number(_a[1]) > Number(_b[1])) {
          return 1;
       }
       return 0;
     });

3 Comments

It will not work for i.e. 10.6
Yes. It is failing for a lot of other numbers. Thanks for the quick response. I hope the sorting is performing on the decimal numbers rather than the actual numbers.
@libik Thanks for the correction. Hope my last edit will work.
1

The decimal values are being treathened the way they should be. Floating point numbers are not the same as version numbers, so it's true that 9.10 is not > 9.2.

But I see what you want to achieve: You want to sort them numbers as if they where version numbers. To achieve your goal, you need to write an own sort algorithm something like this:

my_list.sort(function(a,b){
    var a1 = a['xxx'].split('.');
    var b1 = b['xxx'].split('.');
    var len = Math.max(a1.length, b1.length);

    for(var i = 0; i< len; i++){
        var _a = +a1[i] || 0;
        var _b = +b1[i] || 0;
        if(_a === _b) continue;
        else return _a > _b ? 1 : -1
    }
    return 0;
})

This will give you a result such as:

enter image description here

1 Comment

Thank you for your time and solution. It worked for all the scenarios.
1

Here is a generic solution

let my_list = [
  {"xxx": "9.6", "no_of_occurrence": 1 },
  {"xxx": "9.2", "no_of_occurrence": 1},
  {"xxx": "9.11.3", "no_of_occurrence": 1},
  {"xxx": "9.11.1", "no_of_occurrence": 1},
  {"xxx": "9.10", "no_of_occurrence": 1}
];

my_list.sort((a, b) => {
    let va = a.xxx.split("."), vb = b.xxx.split("."), i = 0
    while(i < va.length && i < vb.length && (+va[i]) == (+vb[i]))
        i++;
    return (+va[i]) - (+vb[i]);
})

console.log(my_list)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.