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

Input Example:

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

Expected Result

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

Attempt; extended from my previous single-line (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 plnkr)

Note. Ranges are guaranteed not to overlap, and there may be other things in the array, such as "foo", that must be placed in any order at the end of the array.

Ideas: I could build a new array, for example [[50,59], ['<', '40']] , and then override the .sort method .sort , but that seems crazy. Is there a better solution?

+5
source share
3 answers

Unfortunately, the other answers did not handle the extreme cases. As an added bonus, no regular expression:

 function sort_ranges(ranges/*: string[]*/)/*: string[]*/ { return ranges.sort((a/*: string*/, b/*: string*/)/*: number*/ => { if (a[0] === '<') return -1; else if (a[0] === '>') return a[0].charCodeAt() - b[0].charCodeAt(); else if (isNaN(parseInt(a[0])) || b[0] === '<') return 1; else if (b[0] === '>' || isNaN(parseInt(b[0]))) return -1; return parseInt(a.split('-')[0]) - parseInt(b.split('-')[0]) }); } // Test code for StackOverflow: const expected_arrays = Object.freeze([ [ '<40', '40-49', '50-59', '60-69', '>=70' ], [ '40-49', '50-59', '60-69', '>=70', 'all' ] ]); const input_arrays = Object.freeze([ [ '60-69', '<40', '>=70', '50-59', '40-49' ], [ '50-59', 'all', '40-49', '>=70', '60-69' ] ]); for(let i=0; i<input_arrays.length; i++) console.info(sort_ranges(input_arrays[i]), '===', expected_arrays[i]); 
0
source

 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 ); 
+7
source

You can match numbers, and if two numbers are available, grab them for adjusted sorting.

 var array = ['50-59', '60-69', '40-49', '>=70', '<40', 'all']; array.sort(function (a, b) { function getV(v) { return v.match(/\d+/g) || [Infinity, Infinity]; } var aa = getV(a), bb = getV(b); return aa[0] - bb[0] || (aa[1] || aa[0]) - (bb[1] || bb[0]); }); console.log(array) 
+2
source

Source: https://habr.com/ru/post/1266306/


All Articles