3

我有一个数组,其中的字符串由点分符号中的数字组成,如下所示:

var arr = ['1.2.5.4', '1.2.5.3'];

我希望能够找到表示最高值的字符串。

我已经试过了

Math.max.apply(null, arr)

由于有多个小数,它根本行不通。

4

4 回答 4

2

您需要为此创建自己的排序子例程,因为它们将被视为版本号。您需要进行左优先比较,比较由句点分隔的每个数字。

这是从另一个答案中窃取的大量代码,与我提到的完全一样:

function assert(x) {
    if (!x) {
        alert("Assert failed");
        debugger;
    }
}

function isPositiveInteger(x) {
    // https://stackoverflow.com/a/1019526/11236
    return /^\d+$/.test(x);
}

/**
 * Compare two software version numbers (e.g. 1.7.1)
 * Returns:
 *
 *  0 if they're identical
 *  negative if v1 < v2
 *  positive if v1 > v2
 *  Nan if they in the wrong format
 *
 *  E.g.:
 *
 *  assert(version_number_compare("1.7.1", "1.6.10") > 0);
 *  assert(version_number_compare("1.7.1", "1.7.10") < 0);
 *
 *  "Unit tests": http://jsfiddle.net/ripper234/Xv9WL/28/
 *
 *  Taken from https://stackoverflow.com/a/6832721/11236
 */
function compareVersionNumbers(v1, v2){
    var v1parts = v1.split('.');
    var v2parts = v2.split('.');

    // First, validate both numbers are true version numbers
    function validateParts(parts) {
        for (var i = 0; i < parts.length; ++i) {
            if (!isPositiveInteger(parts[i])) {
                return false;
            }
        }
        return true;
    }
    if (!validateParts(v1parts) || !validateParts(v2parts)) {
        return NaN;
    }

    for (var i = 0; i < v1parts.length; ++i) {
        if (v2parts.length === i) {
            return 1;
        }

        if (v1parts[i] === v2parts[i]) {
            continue;
        }
        if (v1parts[i] > v2parts[i]) {
            return 1;
        }
        return -1;
    }

    if (v1parts.length != v2parts.length) {
        return -1;
    }

    return 0;
}


assert(compareVersionNumbers("1.7.1", "1.7.10") < 0);
assert(compareVersionNumbers("1.6.1", "1.7.10") < 0);
assert(compareVersionNumbers("1.6.20", "1.7.10") < 0);
assert(compareVersionNumbers("1.7.1", "1.7.10") < 0);
assert(compareVersionNumbers("1.7", "1.7.0") < 0);
assert(compareVersionNumbers("1.7", "1.8.0") < 0);

assert(compareVersionNumbers("1.7.10", "1.7.1") > 0);
assert(compareVersionNumbers("1.7.10", "1.6.1") > 0);
assert(compareVersionNumbers("1.7.10", "1.6.20") > 0);
assert(compareVersionNumbers("1.7.0", "1.7") > 0);
assert(compareVersionNumbers("1.8.0", "1.7") > 0);

assert(compareVersionNumbers("1.7.10", "1.7.10") === 0);
assert(compareVersionNumbers("1.7", "1.7") === 0);

assert(isNaN(compareVersionNumbers("1.7", "1..7")));
assert(isNaN(compareVersionNumbers("1.7", "Bad")));
assert(isNaN(compareVersionNumbers("1..7", "1.7")));
assert(isNaN(compareVersionNumbers("Bad", "1.7")));

alert("All done");
​
于 2012-05-15T19:44:34.693 回答
2

这似乎是一个更简单的解决方案:

function latest (versions) {
  versions.sort (function (a, b) {
    a = a.split ('.');
    b = b.split ('.');   
    for (var i = 0; i < a.length && i < b.length && a[i] === b[i]; i++);
    return ((i === a.length) || (+a[i] < +b[i])) ? 1 : -1;
  });
  return versions[0]; 
}

[
  latest (['1.2.5.4', '1.3.5.3', '1.2.3.4.5', '1.24.2.1', '1.2.52']),
  latest (['1.2.5.4', '1.3.5.3', '1.2.3.4.5', '1.2.52']),
  latest (['1.2.5.4', '1.2.3.4.5', '1.2.52']),
  latest (['1.2.5.4', '1.2.3.4.5'])
]

/* Displays on JS console

    ["1.24.2.1", "1.3.5.3", "1.2.52", "1.2.5.4"]
*/

感谢您的投票,在审查时我注意到我在上面的代码中更正了一个错误。

于 2012-05-17T20:08:11.393 回答
0

在我看来,这是一个“更好”的解决方案(因为选中的那个会修改原始数组,这是邪恶的;)):

function latest(versions) {
    return versions.reduce(function(latest, current){
        var l = latest.split('.'),
            c = current.split('.');
        for (var i=0,len=Math.min(l.length, c.length); i<len; i++){
            if (+l[i] === +c[i]) {
                continue;
            } else {
                return +l[i] < +c[i] ? current : latest;
            }
        }
        return l.length < c.length ? current : latest;
    }, "0");
}

结果与检查的答案完全相同,除了原始数组仍然是原始的。

[
  latest (['1.2.5.4', '1.3.5.3', '1.2.3.4.5', '1.24.2.1', '1.2.52']),
  latest (['1.2.5.4', '1.3.5.3', '1.2.3.4.5', '1.2.52']),
  latest (['1.2.5.4', '1.2.3.4.5', '1.2.52']),
  latest (['1.2.5.4', '1.2.3.4.5'])
]

/* Displays on JS console

    ["1.24.2.1", "1.3.5.3", "1.2.52", "1.2.5.4"]
*/

它利用了reduce专门为此用途而设计的功能。

于 2015-03-09T10:14:10.760 回答
0

这是一个人工排序的实现:

Array.prototype.humanSort = function() {
  return this.sort(function(a, b) {
    aa = a.split('.');
    bb = b.split('.');

    for(var x = 0; x < Math.max(aa.length, bb.length); x++) {
      if(aa[x] != bb[x]) {
        var cmp1 = (isNaN(parseInt(aa[x],10)))? aa[x] : parseInt(aa[x],10);
        var cmp2 = (isNaN(parseInt(bb[x],10)))? bb[x] : parseInt(bb[x],10);
        if(cmp1 == undefined || cmp2 == undefined)
          return aa.length - bb.length;
        else
          return (cmp1 < cmp2) ? -1 : 1;
      }
    }
    return 0;
  });
}

像这样称呼它:

 ['1.12.5.4', '1.2.5.3'].humanSort(); // => ['1.2.5.3', '1.12.5.4']
于 2012-05-15T19:57:15.507 回答