10

Unsorted array [input] :

["> 30 days", "< 7 days", "< 30 days", "< 10 days"];

The format of an elements in array will always be like : </> X days

Requirement :

Above mentioned array should be sorted as per the greater then (>) and lesser then symbol (<) and also keep the number of days in mind (less number of days should come first).

Expected Array [output] :

["< 7 days", "< 10 days", "< 30 days", "> 30 days"];

Tried so far :

I tried Array.sort() function but did not get expected output.

var arr = ["> 30 days", "< 7 days", "< 30 days", "< 10 days"];

var sortedArr = arr.sort();

console.log(sortedArr); // ["< 30 days", "< 10 days", "< 7 days", "> 30 days"]
Debug Diva
  • 26,058
  • 13
  • 70
  • 123

3 Answers3

15

You could sort by numbers and if a comparison sign is available, then take for the same numerical value the delta of both offsets, which reflects the order of comparison.

var array = ["> 30 days", "< 7 days", "30 days", "< 10 days", "> 10 days", "< 11 days", "42 days", ">= 42 days", "> 42 days", "<= 42 days", "< 42 days"];

array.sort(function (a, b) {
    function getV(s) {
        return {
            value: s.match(/\d+/),
            offset: { '<': -2, '<=': -1, null: 0, '>=': 1, '>': 2 }[s.match(/[<>]={0,1}(?=\s*\d)/)]
        };
    }
    var aa = getV(a),
        bb = getV(b);

    return aa.value - bb.value || aa.offset - bb.offset;
});

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

First/former solution

You could parse the string and use it for applying a correction value to the number - then sort accordingly.

{ '>': 0.1, '<': -0.1, null: 0 }[s.match(/[<>](?=\s*\d)/)] + +s.match(/\d+/)

object with correction values

{ '>': 0.1, '<': -0.1, null: 0 }                                    

get the sign with a regular expression and use it as key for the object

                                 s.match(/[<>](?=\s*\d)/)

then add the number part of the string

                                                          + +s.match(/\d+/)

var array = ["> 30 days", "< 7 days", "30 days", "< 10 days"];

array.sort(function (a, b) {
    function getV(s) {
        return { '>': 0.1, '<': -0.1, null: 0 }[s.match(/[<>](?=\s*\d)/)] + +s.match(/\d+/);
    }
    return getV(a) - getV(b);
});

console.log(array);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • It is working like a champ. Thanks for this solution. can you please explain this line of code `{ '>': 0.1, '<': -0.1, null: 0 }[s.match(/[<>](?=\s*\d)/)] + +s.match(/\d+/)`. So that it will helpful for me and other users to solve this type of problem in future by themselves. – Debug Diva Jul 18 '17 at 10:00
0

Another attempt at the problem without regex. I am not good at regex so thought of an alternative way.

         // Attempt to sort without regex.
         var array = ["> 30 days", "< 7 days", "< 30 days", "< 10 days"];

         array.sort(function(a,b){ 
           var first = a.split(" "); 
           var second = b.split(" ");
           if(first[0] < second[0]) {  
               return false; 
           } else if(first[0] > second[0]){ 
               return true; 
           } else { 
              var intFirst = parseInt(first[1]);
              var intSecond = parseInt(second[1]);
              if(intFirst < intSecond){
                return false; 
              } else if(intFirst >= intSecond) {
                return true;
              }
           }
         });
         
         console.log(array);
Jay
  • 1,478
  • 1
  • 10
  • 9
0

Try this code:

customSort();

var arr = ["> 30 days", "< 7 days", "30 days", "< 10 days"];
var arr2 = ["> 30 days", "< 7 days", "< 30 days", "< 10 days"];
  
console.log(customSort(arr));
console.log(customSort(arr2));
  
function customSort(array){
    function getNumber(str) {
        var a={'>': 0.1, '<': -0.1, null: 0};
        return a[str.match(/[<>](?=\s*\d)/)] + Number(str.match(/\d+/)[0]);
    }
    return array.sort(function(a, b){
        return getNumber(a)-getNumber(b);
    });
}
Rashid
  • 272
  • 2
  • 6