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.

Kiran
  • 1,177
  • 4
  • 18
  • 35
  • 2
    This answer on [how to sort version numbers](https://stackoverflow.com/q/40201533/3297291) might help – user3297291 Jun 14 '22 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. – jarmod Jun 14 '22 at 11:31
  • @jarmod: These are version numbers. That means 9.10 is greater than 9.6 – Kiran Jun 14 '22 at 11:45
  • 1
    That's critical context. I've modified the question to clarify. – jarmod Jun 14 '22 at 11:53
  • Does this answer your question? [Sort version-dotted number strings in Javascript?](https://stackoverflow.com/questions/40201533/sort-version-dotted-number-strings-in-javascript) – jarmod Jun 14 '22 at 11:54
  • Thanks for the link @jarmod. This link is same as the one provided by the user3297291. This could solve my problem. But the answers in this thread dealt with simple array of elements. I can extend the answer to cater my need. But fortunately I got the solution I'm looking for from the community of great minds here. Once again thanks for the time and help. – Kiran Jun 14 '22 at 12:03

5 Answers5

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];}));
Carsten Massmann
  • 26,510
  • 2
  • 22
  • 43
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;
     });
Pranavan
  • 1,287
  • 1
  • 6
  • 18
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);
libik
  • 22,239
  • 9
  • 44
  • 87
  • Thanks @liblik. This worked. It worked even for the numbers like ".31" and "15" as well. – Kiran Jun 14 '22 at 11:51
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

lucamuh
  • 1,235
  • 2
  • 8
  • 12
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)
Madhusoodan P
  • 681
  • 9
  • 20