【问题标题】:Sort array of ranges ['55-66', '>55', '<66']?排序范围数组 ['55-66', '>55', '<66']?
【发布时间】:2017-08-29 16:27:20
【问题描述】:

示例输入:

[ '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)

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

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

【问题讨论】:

  • 我不明白为什么40-49 之前的60-6950-59 在预期结果中。
  • 哎呀,我的错;匆忙复制过来
  • 51-57 会去哪里?
  • 保证范围不重叠
  • James: parseInt 这样做了,但是当我在数组中有其他东西是 NaN 时,我遇到了问题。这就是最初出现isNaN 代码的原因。还有 mplungjan 所说的

标签: javascript arrays sorting typescript range


【解决方案1】:

您可以匹配数字,如果有两个数字可用,则将其用于调整排序。

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)

【讨论】:

  • 如果return 中的任何元素为空怎么办?
  • 你可以添加一个默认值,比如return (aa[0] || 0) - (bb[0] || 0) || (aa[1] || aa[0] || 0) - (bb[1] || bb[0] || 0);
  • TypeError: bb is null。 PS:查看我对工作模型的回答
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2014-01-28
      • 2016-10-22
      • 1970-01-01
      • 2019-06-11
      • 2017-06-05
      • 2014-09-18
      • 2016-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多