对数组范围进行排序[' 55-66','>'''BB#66;#?

时间:2017-04-04 12:50:55

标签: javascript arrays sorting typescript range

示例输入:

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

预期输出

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

尝试;从我之前的单行扩展(用于调试):

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)

注意:范围保证不重叠,并且数组中可能还有其他内容,例如&#39; foo&#39;应该以数组末尾的任何顺序放置。

想法:我可以构建一个像[[50,59], ['<', '40']]这样的新数组,然后尝试再次覆盖.sort方法,但这看起来很疯狂。有更好的解决方案吗?

3 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:2)

您可以匹配数字,如果有两个数字可用,请将其作为调整后的排序。

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 :(得分:0)

不幸的是,其他答案并没有处理边缘情况。作为额外的奖励,没有正则表达式:

&#13;
&#13;
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]);
&#13;
&#13;
&#13;