Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort array of ranges ['55-66', '>55', '<66']?

Example input:

[ '50-59', '60-69', '40-49', '>=70', '<40' ]

Expected output

[ '<40', '40-49', '50-59', '60-69', '>=70' ]

Attempt; expanded from my previous one-liner (for debugging):

export function sort_ranges(ranges: string[]): string[] {
    const collator = new Intl.Collator(undefined, {
        numeric: true,
        sensitivity: 'base',
        ignorePunctuation: true
    });
    return ranges.sort((a: string, b: string): number => {
            const bNaN: boolean = !isNaN(parseInt(b[0]));
            const col = () =>
                console.info(`collator(${a}, ${b}) = ${collator.compare(a, b)}`
                            ) || collator.compare(a, b);
            if (a[0] === '<' && bNaN) {
                console.info('< =', a);
                return -1;
            }
            else if (a[0] === '>' || b[0] === '>') {
                console.info('> =', a);
                return 1;
            }
            else return col();
        }
    );
}

Runnable (mocha+chai in a plnkr)

Note: ranges are guaranteed to be non-overlapping, and there may be other things in the array like 'foo' which should be put in whatever order at the end of the array.

Ideas: I could build a new array like [[50,59], ['<', '40']] then try overriding the .sort method again, but that seems crazy. Is there a better solution?

like image 797
A T Avatar asked Apr 04 '17 12:04

A T


1 Answers

var a = [ '50-59', '60-69', '40-49', '>=70', '<40' ];

a.sort(function(a,b) {
  if (a[0] === '<') return -1;
  if (a[0] === '>') return 1;
  if (b[0] === '<') return 1;
  if (b[0] === '>') return -1;
  return a.match(/\d+/)[0] - b.match(/\d+/)[0];
});

console.dir( a );
like image 199
ki11en Avatar answered Oct 03 '22 01:10

ki11en