ドット付き表記の数値で構成される文字列を含む配列があります。
var arr = ['1.2.5.4', '1.2.5.3'];
最高値を表す文字列を見つけられるようにしたいと思います。
私はすでに試しました
Math.max.apply(null, arr)
小数点以下が複数あるため、機能しません。
ドット付き表記の数値で構成される文字列を含む配列があります。
var arr = ['1.2.5.4', '1.2.5.3'];
最高値を表す文字列を見つけられるようにしたいと思います。
私はすでに試しました
Math.max.apply(null, arr)
小数点以下が複数あるため、機能しません。
バージョン番号として扱われるため、このために独自のソートサブルーチンを作成する必要があります。ピリオドで区切られた各数値を比較して、左から最初の比較を行うことをお勧めします。
これは、私が述べたとおりに機能する別の回答から盗まれたコードのかなりの部分です。
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");
これはより簡単な解決策のようです:
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"]
*/
投票してくれてありがとう、レビューで私は上記のコードで修正したバグに気づきました。
これが人間によるソートの実装です。
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']
これが私の意見に対する「より良い」解決策です(チェックされたものは元の配列を変更するため、これは悪です;)):
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
、それはまさにこの使用法のために作られた機能を利用しています。