【问题标题】:sorting version numbers stored as string in an array对存储为数组中的字符串的版本号进行排序
【发布时间】:2017-12-21 14:15:24
【问题描述】:

假设我有一个这样的数组:

let arr = ["1.2.5", "1", "10", "2.0.4", "3.3.3.3"];

对此进行排序并获得如下结果的最佳方法是什么:
let arr = ["1", "1.2.5", "2.0.4", "3.3.3.3", "10"];

首先我想将数组中的每个项目转换为“浮点数”可能会起作用,但随后多个小数不会给出预期的结果。

我也可以进行for 循环并执行item.split(".") 之类的操作,然后一一检查,但我认为这不是最好的方法。

有什么建议吗?

【问题讨论】:

  • 3.3.3.3 是一个数字吗?不对吧?
  • 是的,我知道,但我不知道我还叫什么来解释我期望的结果。不过我希望你能明白我的意思。
  • 2.0.4 与其他数字不同,因此不能像数字那样排序。
  • 好的,我想要的不是“像数字一样排序”,而是排序。请让我知道我是否可以重写我的问题以便更好地解释。
  • 您可以尝试按第一个数字排序。 arr.sort(function(a,b){ return a.split('.')[0] - b.split('.')[0]; });

标签: javascript arrays performance sorting


【解决方案1】:
  • 排序1.0a 符号正确
  • 使用原生localeCompare1.090 表示法进行排序

function log(label,val){
  document.body.append(label,String(val).replace(/,/g," - "),document.createElement("BR"));
}

const sortVersions = (
  x,
  v = s => s.match(/[a-z]|\d+/g).map(c => c==~~c ? String.fromCharCode(97 + c) : c)
) => x.sort((a, b) => (a + b).match(/[a-z]/) 
                             ? v(b) < v(a) ? 1 : -1 
                             : a.localeCompare(b, 0, {numeric: true}))

let v=["1.90.1","1.090","1.0a","1.0.1","1.0.0a","1.0.0b","1.0.0.1","1.0a"];
log(' input : ',v);
log('sorted: ',sortVersions(v));
log('no dups:',[...new Set(sortVersions(v))]);

【讨论】:

    【解决方案2】:

    您可以将String#localeCompareoptions 一起使用

    灵敏度

    字符串中的哪些差异应导致非零结果值。可能的值是:

    • "base":只有基本字母不同的字符串比较不相等。示例:a ≠ ba = áa = A
    • "accent":只有在基本字母或重音和其他变音符号不同的字符串比较为不相等。示例:a ≠ ba ≠ áa = A
    • "case":只有基本字母或大小写不同的字符串比较不相等。示例:a ≠ ba = áa ≠ A
    • "variant":基本字母、重音符号和其他变音符号不同的字符串,或者大小写比较不相等。也可以考虑其他差异。示例:a ≠ ba ≠ áa ≠ A

    使用“排序”的默认值为“变体”;它依赖于使用“搜索”的语言环境。

    数字

    是否应使用数字排序规则,例如“1”true 和false;默认为false。可以通过选项属性或通过 Unicode 扩展键设置此选项;如果两者都提供,options 属性优先。实现不需要支持此属性。

    var array = ["1.2.5", "1", "10", "2.0.4", "3.3.3.3"];
    
    array.sort(function (a,b) {
        return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });
    });
    
    console.log(array);

    【讨论】:

      【解决方案3】:

      var arr = ["1.2.5", "1", "10", "2.0.4", "3.3.3.3"];

      var arr = ["1.2.5", "1", "10", "2.0.4", "3.3.3.3"];
      console.log(arr.sort(function(a,b){
      
        var arr1 = a.split('.');
        var arr2 = b.split('.');
        
        var maxlen = Math.max(arr1.length,arr2.length);
        
        var i;
      
        for(i = 0;i<maxlen;i++){
        		var i1 = parseInt(arr1[i] || 0)
            var i2 = parseInt(arr2[i] || 0)
      			if(i1 < i2){
            			return -1;
            }
            else if(i1 > i2){
            			return 1;
            }
        }
        
        return 0;
      
      }));

      【讨论】:

        【解决方案4】:

        这是我的解决方案(使用 ES6 语法)

        const arr = ["1.2.5", "1", "10", "2.0.4", "3.3.3.3"];
        
        const result = arr
        .map((n) => n.split('.').map((c) => c.padStart(10, '0')).join('.'))
        .sort()
        .map((n) => n.split('.').map((c) => +c).join('.'))
        
        console.log(result);

        【讨论】:

        • 你能解释一下吗
        • 第一个 map() 添加前导零,即它执行以下转换 "1.2.3" => "0000000001.0000000002.0000000003" 并且之后排序正常工作。第二个 map() 只是删除前导零。
        • 嗯,这是一个很好的方法,感谢您的解释。我不知道 padStart
        【解决方案5】:
        function compare(a, b) {
            var aSplit = a.split(".");
            var bSplit = b.split(".");
        
        
            var length = Math.min(aSplit.length, bSplit.length);
            for (var i = 0; i < length; ++i) {
                if (parseInt(aSplit[i]) < parseInt(bSplit[i])) {
                    return -1;
                } else if (parseInt(aSplit[i]) > parseInt(bSplit[i])) {
                    return 1;
                }
            }
        
            if (aSplit.length < bSplit.length) {
                return -1;
            } else if (aSplit.length > bSplit.length) {
                return 1;
            }
        
            return 0;
        }
        

        你可以像这样使用它:arr.sort((a, b) => compare(a, b));

        【讨论】:

          猜你喜欢
          • 2020-02-13
          • 1970-01-01
          • 1970-01-01
          • 2016-10-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多