Tat*_*tat 145 javascript sorting
这是软件版本号:
"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"
Run Code Online (Sandbox Code Playgroud)
我该如何比较?假设正确的顺序是:
"1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"
Run Code Online (Sandbox Code Playgroud)
这个想法很简单......:读取第一个数字,然后读取第二个数字,然后读取第三个数字....但是我无法将版本号转换为浮点数....你也可以看到版本号就像这个:
"1.0.0.0", "1.0.1.0", "2.0.0.0", "2.0.0.1", "2.0.1.0"
Run Code Online (Sandbox Code Playgroud)
这更清楚地看到背后的想法是什么......但是,如何将其转换为计算机程序?有没有人知道如何排序这个?谢谢.
Jon*_*Jon 122
进行这种比较的基本思想是用来Array.split从输入字符串中获取部件数组,然后比较两个数组中的部件对; 如果部件不相等,我们知道哪个版本更小.
需要记住的一些重要细节:
这是您可以直接使用的实现的代码(gist with documentation):
function versionCompare(v1, v2, options) {
var lexicographical = options && options.lexicographical,
zeroExtend = options && options.zeroExtend,
v1parts = v1.split('.'),
v2parts = v2.split('.');
function isValidPart(x) {
return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x);
}
if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
return NaN;
}
if (zeroExtend) {
while (v1parts.length < v2parts.length) v1parts.push("0");
while (v2parts.length < v1parts.length) v2parts.push("0");
}
if (!lexicographical) {
v1parts = v1parts.map(Number);
v2parts = v2parts.map(Number);
}
for (var i = 0; i < v1parts.length; ++i) {
if (v2parts.length == i) {
return 1;
}
if (v1parts[i] == v2parts[i]) {
continue;
}
else if (v1parts[i] > v2parts[i]) {
return 1;
}
else {
return -1;
}
}
if (v1parts.length != v2parts.length) {
return -1;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该版本自然地比较部分,不接受字符后缀并认为"1.7"小于"1.7.0".比较模式可以更改为词典编纂,较短版本的字符串可以使用可选的第三个参数自动进行零填充.
有一个JSFiddle 在这里运行"单元测试" ; 它是ripper234工作的略微扩展版本(谢谢).
重要说明:此代码使用Array.map和Array.every,这意味着它不会在早于9的IE版本中运行.如果需要支持那些,则必须为缺少的方法提供polyfill.
小智 67
semver
npm使用的语义版本解析器.
$ npm install semver
var semver = require('semver');
semver.diff('3.4.5', '4.3.7') //'major'
semver.diff('3.4.5', '3.3.7') //'minor'
semver.gte('3.4.8', '3.4.7') //true
semver.ltr('3.4.8', '3.4.7') //false
semver.valid('1.2.3') // '1.2.3'
semver.valid('a.b.c') // null
semver.clean(' =v1.2.3 ') // '1.2.3'
semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
semver.gt('1.2.3', '9.8.7') // false
semver.lt('1.2.3', '9.8.7') // true
var versions = [ '1.2.3', '3.4.5', '1.0.2' ]
var max = versions.sort(semver.rcompare)[0]
var min = versions.sort(semver.compare)[0]
var max = semver.maxSatisfying(versions, '*')
Run Code Online (Sandbox Code Playgroud)
语义版本链接:https:
//www.npmjs.com/package/semver#prerelease-identifiers
Joe*_*Joe 48
// Return 1 if a > b
// Return -1 if a < b
// Return 0 if a == b
function compare(a, b) {
if (a === b) {
return 0;
}
var a_components = a.split(".");
var b_components = b.split(".");
var len = Math.min(a_components.length, b_components.length);
// loop while the components are equal
for (var i = 0; i < len; i++) {
// A bigger than B
if (parseInt(a_components[i]) > parseInt(b_components[i])) {
return 1;
}
// B bigger than A
if (parseInt(a_components[i]) < parseInt(b_components[i])) {
return -1;
}
}
// If one's a prefix of the other, the longer one is greater.
if (a_components.length > b_components.length) {
return 1;
}
if (a_components.length < b_components.length) {
return -1;
}
// Otherwise they are the same.
return 0;
}
console.log(compare("1", "2"));
console.log(compare("2", "1"));
console.log(compare("1.0", "1.0"));
console.log(compare("2.0", "1.0"));
console.log(compare("1.0", "2.0"));
console.log(compare("1.0.1", "1.0"));
Run Code Online (Sandbox Code Playgroud)
LeJ*_*red 42
这个非常小但速度非常快的比较函数可以获取任何长度的版本号和每个段的任何数字大小.
返回值:
- 一个数字,< 0如果a <b
- 一个数字,> 0如果a> b
- 0如果a = b
所以你可以用它作为Array.sort()的比较函数;
编辑: Bugfixed版本剥离尾随零以识别"1"和"1.0.0"相等
function cmpVersions (a, b) {
var i, diff;
var regExStrip0 = /(\.0+)+$/;
var segmentsA = a.replace(regExStrip0, '').split('.');
var segmentsB = b.replace(regExStrip0, '').split('.');
var l = Math.min(segmentsA.length, segmentsB.length);
for (i = 0; i < l; i++) {
diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10);
if (diff) {
return diff;
}
}
return segmentsA.length - segmentsB.length;
}
// TEST
console.log(
['2.5.10.4159',
'1.0.0',
'0.5',
'0.4.1',
'1',
'1.1',
'0.0.0',
'2.5.0',
'2',
'0.0',
'2.5.10',
'10.5',
'1.25.4',
'1.2.15'].sort(cmpVersions));
// Result:
// ["0.0.0", "0.0", "0.4.1", "0.5", "1.0.0", "1", "1.1", "1.2.15", "1.25.4", "2", "2.5.0", "2.5.10", "2.5.10.4159", "10.5"]Run Code Online (Sandbox Code Playgroud)
Ida*_*dan 15
最简单的是使用localeCompare:
a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' })
Run Code Online (Sandbox Code Playgroud)
这将返回:
0: 版本字符串相等 1: 版本a大于b-1: 版本b大于ause*_*621 14
取自http://java.com/js/deployJava.js:
// return true if 'installed' (considered as a JRE version string) is
// greater than or equal to 'required' (again, a JRE version string).
compareVersions: function (installed, required) {
var a = installed.split('.');
var b = required.split('.');
for (var i = 0; i < a.length; ++i) {
a[i] = Number(a[i]);
}
for (var i = 0; i < b.length; ++i) {
b[i] = Number(b[i]);
}
if (a.length == 2) {
a[2] = 0;
}
if (a[0] > b[0]) return true;
if (a[0] < b[0]) return false;
if (a[1] > b[1]) return true;
if (a[1] < b[1]) return false;
if (a[2] > b[2]) return true;
if (a[2] < b[2]) return false;
return true;
}
Run Code Online (Sandbox Code Playgroud)
无法在这里找到我想做的功能.所以我写了自己的.这是我的贡献.我希望有人觉得它很有用.
优点:
处理任意长度的版本字符串.'1'或'1.1.1.1.1'.
如果未指定,则将每个值默认为0.仅仅因为字符串更长并不意味着它是一个更大的版本.('1'应与'1.0'和'1.0.0.0'相同.)
比较数字而非字符串.('3'<'21'应该是真的.不是假的.)
不要在循环中浪费时间在无用的比较上.(比较==)
您可以选择自己的比较器.
缺点:
我的代码,类似于Jon接受的答案:
function compareVersions(v1, comparator, v2) {
"use strict";
var comparator = comparator == '=' ? '==' : comparator;
if(['==','===','<','<=','>','>=','!=','!=='].indexOf(comparator) == -1) {
throw new Error('Invalid comparator. ' + comparator);
}
var v1parts = v1.split('.'), v2parts = v2.split('.');
var maxLen = Math.max(v1parts.length, v2parts.length);
var part1, part2;
var cmp = 0;
for(var i = 0; i < maxLen && !cmp; i++) {
part1 = parseInt(v1parts[i], 10) || 0;
part2 = parseInt(v2parts[i], 10) || 0;
if(part1 < part2)
cmp = 1;
if(part1 > part2)
cmp = -1;
}
return eval('0' + comparator + cmp);
}
Run Code Online (Sandbox Code Playgroud)
示例:
compareVersions('1.2.0', '==', '1.2'); // true
compareVersions('00001', '==', '1.0.0'); // true
compareVersions('1.2.0', '<=', '1.2'); // true
compareVersions('2.2.0', '<=', '1.2'); // false
Run Code Online (Sandbox Code Playgroud)
你可以String#localeCompare使用options
\n\n灵敏度
\n字符串中的哪些差异应导致非零结果值。可能的值为:
\n\n
\n- \n
"base":只有基本字母不同的字符串才比较为不相等。例子:a \xe2\x89\xa0 b,a = \xc3\xa1,a = A。- \n
"accent":只有基本字母或重音符号以及其他变音符号不同的字符串才会被视为不相等。例子:a \xe2\x89\xa0 b,a \xe2\x89\xa0 \xc3\xa1,a = A。- \n
"case":只有基本字母或大小写不同的字符串才比较为不相等。例子:a \xe2\x89\xa0 b,a = \xc3\xa1,a \xe2\x89\xa0 A。- \n
"variant":基本字母、重音符号和其他变音符号不同或大小写不同的字符串比较为不相等。还可以考虑其他差异。例子:a \xe2\x89\xa0 b,a \xe2\x89\xa0 \xc3\xa1,a \xe2\x89\xa0 A。默认为“variant”,用于“sort”用法;它的使用“搜索”取决于区域设置。
\n数字
\n是否应使用数字排序规则,例如“1”<“2”<“10”。可能的值为
\ntrue和false;默认为false. 该选项可以通过选项属性或通过 Unicode 扩展键来设置;如果两者都提供,则options属性优先。不需要实现来支持此属性。
var versions = ["2.0.1", "2.0", "1.0", "1.0.1", "2.0.0.1"];\n\nversions.sort((a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: \'base\' }));\n\nconsole.log(versions);Run Code Online (Sandbox Code Playgroud)\r\n这是另一个短版本,适用于任意数量的子版本、填充零甚至带字母的数字 (1.0.0b3)
function compareVer(a, b)
{
function prep(t)
{
return ("" + t)
//treat non-numerical characters as lower version
//replacing them with a negative number based on charcode of first character
.replace(/[^0-9\.]+/g, function(c){return "." + ((c = c.replace(/[\W_]+/, "")) ? c.toLowerCase().charCodeAt(0) - 65536 : "") + "."})
//remove trailing "." and "0" if followed by non-numerical characters (1.0.0b);
.replace(/(?:\.0+)*(\.-[0-9]+)(\.[0-9]+)?\.*$/g, "$1$2")
.split('.');
}
a = prep(a);
b = prep(b);
for (var i = 0; i < Math.max(a.length, b.length); i++)
{
//convert to integer the most efficient way
a[i] = ~~a[i];
b[i] = ~~b[i];
if (a[i] > b[i])
return 1;
else if (a[i] < b[i])
return -1;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
函数返回:
0 : a = b
1 : a > b
-1 : a < b
1.0 = 1.0.0.0.0.0
1.0 < 1.0.1
1.0b1 < 1.0
1.0b = 1.0b
1.1 > 1.0.1b
1.1alpha < 1.1beta
1.1rc1 > 1.1beta
1.1rc1 < 1.1rc2
1.1.0a1 < 1.1a2
1.1.0a10 > 1.1.0a1
1.1.0alpha = 1.1a
1.1.0alpha2 < 1.1b1
1.0001 > 1.00000.1.0.0.0.01
Run Code Online (Sandbox Code Playgroud)
/*use strict*/
function compareVer(a, b)
{
a = compareVer.prep(a);
b = compareVer.prep(b);
for (var i = 0; i < Math.max(a.length, b.length); i++)
{
//convert to integer the most efficient way
a[i] = ~~a[i];
b[i] = ~~b[i];
if (a[i] > b[i])
return 1;
else if (a[i] < b[i])
return -1;
}
return 0;
}
compareVer.prep = t => ("" + t)
//treat non-numerical characters as lower version
//replacing them with a negative number based on charcode of first character
.replace(/[^0-9\.]+/g, c => "." + ((c = c.replace(/[\W_]+/, "")) ? c.toLowerCase().charCodeAt(0) - 65536 : "") + ".")
//remove trailing "." and "0" if followed by non-numerical characters (1.0.0b);
.replace(/(?:\.0+)*(\.-[0-9]+)(\.[0-9]+)?\.*$/g, "$1$2")
.split('.');
//examples
var type = {
"-1": " < ",
"0": " = ",
"1": " > "
}
var list = [
["1.0", "1.0.0.0.0.0"],
["1.0", "1.0.1"],
["1.0b1", "1.0"],
["1.0b", "1.0b"],
["1.1", "1.0.1b"],
["1.1alpha", "1.1beta"],
["1.1rc1", "1.1beta"],
["1.1rc1", "1.1rc2"],
["1.1.0a1", "1.1a2"],
["1.1.0a10", "1.1.0a1"],
["1.1.0alpha", "1.1a"],
["1.1.0alpha2", "1.1b1"],
["1.0001", "1.00000.1.0.0.0.01"]
]
for(var i = 0, t; i < list.length; i++)
{
t = list[i][0] + type[compareVer(list[i][0], list[i][1])] + list[i][1]
document.body.innerHTML += t + "<br>";
console.log(t);
}Run Code Online (Sandbox Code Playgroud)
https://jsfiddle.net/vanowm/p7uvtbor/
2017年答案:
v1 = '20.0.12';
v2 = '3.123.12';
compareVersions(v1,v2)
// return positive: v1 > v2, zero:v1 == v2, negative: v1 < v2
function compareVersions(v1, v2) {
v1= v1.split('.')
v2= v2.split('.')
var len = Math.max(v1.length,v2.length)
/*default is true*/
for( let i=0; i < len; i++)
v1 = Number(v1[i] || 0);
v2 = Number(v2[i] || 0);
if (v1 !== v2) return v1 - v2 ;
i++;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现代浏览器的最简单代码:
function compareVersion2(ver1, ver2) {
ver1 = ver1.split('.').map( s => s.padStart(10) ).join('.');
ver2 = ver2.split('.').map( s => s.padStart(10) ).join('.');
return ver1 <= ver2;
}
Run Code Online (Sandbox Code Playgroud)
这里的想法是比较数字,但以字符串的形式。为了进行比较,两个字符串的长度必须相同。所以:
"123" > "99"成为"123" > "099"
填充短数字“修复”比较
在这里,我用零填充每个部分到 10 的长度。然后只需使用简单的字符串比较作为答案
例子 :
var ver1 = '0.2.10', ver2=`0.10.2`
//become
ver1 = '0000000000.0000000002.0000000010'
ver2 = '0000000000.0000000010.0000000002'
// then it easy to see that
ver1 <= ver2 // true
Run Code Online (Sandbox Code Playgroud)
小智 6
我遇到了类似的问题,并且我已经为其创建了解决方案。请随意尝试一下。
它返回0for equal,1如果版本是greater并且-1如果是less
function compareVersion(currentVersion, minVersion) {
let current = currentVersion.replace(/\./g," .").split(' ').map(x=>parseFloat(x,10))
let min = minVersion.replace(/\./g," .").split(' ').map(x=>parseFloat(x,10))
for(let i = 0; i < Math.max(current.length, min.length); i++) {
if((current[i] || 0) < (min[i] || 0)) {
return -1
} else if ((current[i] || 0) > (min[i] || 0)) {
return 1
}
}
return 0
}
console.log(compareVersion("81.0.1212.121","80.4.1121.121"));
console.log(compareVersion("81.0.1212.121","80.4.9921.121"));
console.log(compareVersion("80.0.1212.121","80.4.9921.121"));
console.log(compareVersion("4.4.0","4.4.1"));
console.log(compareVersion("5.24","5.2"));
console.log(compareVersion("4.1","4.1.2"));
console.log(compareVersion("4.1.2","4.1"));
console.log(compareVersion("4.4.4.4","4.4.4.4.4"));
console.log(compareVersion("4.4.4.4.4.4","4.4.4.4.4"));
console.log(compareVersion("0","1"));
console.log(compareVersion("1","1"));
console.log(compareVersion("1","1.0.00000.0000"));
console.log(compareVersion("","1"));
console.log(compareVersion("10.0.1","10.1"));Run Code Online (Sandbox Code Playgroud)
version_compare()检查php.js 项目中的函数。它类似于PHP 的 version_compare().
您可以像这样简单地使用它:
version_compare('2.0', '2.0.0.1', '<');
// returns true
Run Code Online (Sandbox Code Playgroud)
小智 5
如果这个想法已经在我没有看到的链接中被访问过,请原谅我。
我在将部分转换为加权总和方面取得了一些成功,如下所示:
partSum = this.major * Math.Pow(10,9);
partSum += this.minor * Math.Pow(10, 6);
partSum += this.revision * Math.Pow(10, 3);
partSum += this.build * Math.Pow(10, 0);
Run Code Online (Sandbox Code Playgroud)
这使得比较非常容易(比较双精度)。我们的版本字段永远不会超过 4 位数字。
7.10.2.184 -> 7010002184.0
7.11.0.1385 -> 7011001385.0
Run Code Online (Sandbox Code Playgroud)
我希望这对某人有所帮助,因为多个条件似乎有点矫枉过正。
Simple and short function:
function isNewerVersion (oldVer, newVer) {
const oldParts = oldVer.split('.')
const newParts = newVer.split('.')
for (var i = 0; i < newParts.length; i++) {
const a = parseInt(newParts[i]) || 0
const b = parseInt(oldParts[i]) || 0
if (a > b) return true
if (a < b) return false
}
return false
}
Run Code Online (Sandbox Code Playgroud)
Tests:
isNewerVersion('1.0', '2.0') // true
isNewerVersion('1.0', '1.0.1') // true
isNewerVersion('1.0.1', '1.0.10') // true
isNewerVersion('1.0.1', '1.0.1') // false
isNewerVersion('2.0', '1.0') // false
isNewerVersion('2', '1.0') // false
isNewerVersion('2.0.0.0.0.1', '2.1') // true
isNewerVersion('2.0.0.0.0.1', '2.0') // false
Run Code Online (Sandbox Code Playgroud)
尽管这个问题已经有很多答案,但每个人都在推广自己的后院酿造解决方案,而我们为此拥有一个完整的(经过战斗)测试的库生态系统。
快速搜索NPM、GitHub、 X 会给我们一些可爱的库,我想浏览一些:
semver-compare是一个很棒的轻量级 (~230B) 库,如果您想按版本号排序,因为库的公开方法返回-1,0或1适当地,它特别有用。
库的核心:
module.exports = function cmp (a, b) {
var pa = a.split('.');
var pb = b.split('.');
for (var i = 0; i < 3; i++) {
var na = Number(pa[i]);
var nb = Number(pb[i]);
if (na > nb) return 1;
if (nb > na) return -1;
if (!isNaN(na) && isNaN(nb)) return 1;
if (isNaN(na) && !isNaN(nb)) return -1;
}
return 0;
};
Run Code Online (Sandbox Code Playgroud)
compare-semver 大小相当大(约 4.4kB gzipped),但允许一些很好的独特比较,比如找到一堆版本的最小值/最大值,或者找出所提供的版本是唯一的还是比集合中的任何其他版本都少版本。
compare-versions是另一个小库(~630B gzipped)并很好地遵循规范,这意味着您可以将版本与 alpha/beta 标志甚至通配符进行比较(例如次要/补丁版本:1.0.x或1.0.*)
重点是:如果您可以通过您选择的包管理器找到合适的(单元)测试版本,则并不总是需要从 StackOverflow 复制粘贴代码。
我们现在可以使用Intl.CollatorAPI 来创建数字比较器。浏览器支持相当不错,但在撰写本文时 Node.js 还不支持。
const semverCompare = new Intl.Collator("en", { numeric: true }).compare;
const versions = ['1.0.1', '1.10.2', '1.1.1', '1.10.1', '1.5.10', '2.10.0', '2.0.1'];
console.log(versions.sort(semverCompare))
const example2 = ["1.0", "1.0.1", "2.0", "2.0.0.1", "2.0.1"];
console.log(example2.sort(semverCompare))Run Code Online (Sandbox Code Playgroud)
Nina Scholz在 2020 年 3 月和 Sid Vishnoi在 2020 年 4 月都发布了现代答案:
var versions = ["2.0.1", "2.0", "1.0", "1.0.1", "2.0.0.1"];
versions.sort((a, b) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' })
);
console.log(versions);
Run Code Online (Sandbox Code Playgroud)
localCompare 已经存在了一段时间了
localCompare 没有解决这个问题,仍然返回1.0.1 , 1.0a
Michael Deal 在他的(又长又复杂)的解决方案中已经在 2013 年破解了这个问题
他将Numbers转换为另一个Base,以便更好地排序
他的回答让我思考...
排序是基于 ASCII 值的字母数字,所以让我们(ab)使用 ASCII 作为“基础”
我的解决方案是将1.0.2.1转换为 bacb为 bacb,然后排序
这可以通过以下方式解决1.1与1.0.0.0.1 的问题:bb与baaab
并立即解决了1.0a和1.0.1 的排序问题,符号为:baa和bab
转换是通过以下方式完成的:
const str = s => s.match(/(\d+)|[a-z]/g)
.map(c => c == ~~c ? String.fromCharCode(97 + c) : c);
Run Code Online (Sandbox Code Playgroud)
= 计算 0...999 数字的 ASCII 值,否则连接字母
1.0a>>> [ "1" , "0" , "a" ]>>>[ "b" , "a" , "a" ]
为了进行比较,无需将其连接到一个字符串.join("")
const sortVersions=(x,v=s=>s.match(/(\d+)|[a-z]/g)
.map(c=>c==~~c?String.fromCharCode(97+c):c))
=>x.sort((a,b)=>v(b)<v(a)?1:-1)
Run Code Online (Sandbox Code Playgroud)
var versions = ["2.0.1", "2.0", "1.0", "1.0.1", "2.0.0.1"];
versions.sort((a, b) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' })
);
console.log(versions);
Run Code Online (Sandbox Code Playgroud)
请注意1.090在两个结果中的排序方式。
我的代码无法解决一个答案中提到的001.012.001符号,但它localeCompare正确地解决了这部分挑战。
您可以结合使用这两种方法:
.localCompareOR排序versionCompare const str = s => s.match(/(\d+)|[a-z]/g)
.map(c => c == ~~c ? String.fromCharCode(97 + c) : c);
Run Code Online (Sandbox Code Playgroud)
一个非常简单的方法:
function compareVer(previousVersion, currentVersion) {
try {
const [prevMajor, prevMinor = 0, prevPatch = 0] = previousVersion.split('.').map(Number);
const [curMajor, curMinor = 0, curPatch = 0] = currentVersion.split('.').map(Number);
if (curMajor > prevMajor) {
return 'major update';
}
if (curMajor < prevMajor) {
return 'major downgrade';
}
if (curMinor > prevMinor) {
return 'minor update';
}
if (curMinor < prevMinor) {
return 'minor downgrade';
}
if (curPatch > prevPatch) {
return 'patch update';
}
if (curPatch < prevPatch) {
return 'patch downgrade';
}
return 'same version';
} catch (e) {
return 'invalid format';
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
compareVer("3.1", "3.1.1") // patch update
compareVer("3.1.1", "3.2") // minor update
compareVer("2.1.1", "1.1.1") // major downgrade
compareVer("1.1.1", "1.1.1") // same version
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
68335 次 |
| 最近记录: |