有人能为我验证一下吗?JavaScript没有一个版本的strcmp(),所以你必须编写类似下面的代码:
( str1 < str2 ) ?
-1 :
( str1 > str2 ? 1 : 0 );
有人能为我验证一下吗?JavaScript没有一个版本的strcmp(),所以你必须编写类似下面的代码:
( str1 < str2 ) ?
-1 :
( str1 > str2 ? 1 : 0 );
那么问题来了
str1.localeCompare(str2)
localeCompare()
在不同的浏览器中有时表现不同。 - Varda Elentári正如你所指出的那样,JavaScript 并没有这个功能。
一个快速搜索得出了以下结果:
function strcmp ( str1, str2 ) {
// http://kevin.vanzonneveld.net
// + original by: Waldo Malqui Silva
// + input by: Steve Hilder
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + revised by: gorthaur
// * example 1: strcmp( 'waldo', 'owald' );
// * returns 1: 1
// * example 2: strcmp( 'owald', 'waldo' );
// * returns 2: -1
return ( ( str1 == str2 ) ? 0 : ( ( str1 > str2 ) ? 1 : -1 ) );
}
这段内容来源于http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_strcmp/
当然,如果需要的话,你可以添加localeCompare方法:
if (typeof(String.prototype.localeCompare) === 'undefined') {
String.prototype.localeCompare = function(str, locale, options) {
return ((this == str) ? 0 : ((this > str) ? 1 : -1));
};
}
无需担心本地浏览器是否已经包含,可以在代码中的任何地方使用 str1.localeCompare(str2)
。唯一的问题是,如果你关心这个,你需要添加对locales
和options
的支持。
==
而不是 ===
,因为后者避免了类型转换,因而更快一些。 - Tokimonvar a = this.toUpperCase(); var b = str.toUpperCase(); return ((a == b) ? 0 : ((a > b) ? 1 : -1));
- KiplocaleCompare()
很慢,所以如果您不关心非英语字符字符串的“正确”排序,请尝试您原来的方法或更简洁的:
str1 < str2 ? -1 : +(str1 > str2)
在我的机器上,这比localeCompare()
快了一个数量级。
+
确保答案始终是数字而不是布尔值。
(str1 > str2) - (str1 < str2)
。这个表达式的意思不变,但它看起来更整洁易读。 - Jonathan Gilbertvar strcmp = new Intl.Collator(undefined, {numeric:true, sensitivity:'base'}).compare;
用法: strcmp(string1, string2)
结果: 1
表示string1比string2大,0
表示相等,-1
表示string2比string1大。
这比 String.prototype.localeCompare
更高效。
另外,numeric:true
使它执行逻辑数字比较。
===
运算符来检查它们是否相等。e + ◌́ = é
)的字符时,您需要在比较相等之前先对其进行规范化,如下所示-
s1.normalize() === s2.normalize()
function strcmp( a, b ) {
for( let i=0 ; i<Math.min( a.length, b.length ) ; i++ ) {
const n = a.charCodeAt(i) - b.charCodeAt(i);
if( n ) return n && ( ( n>>31 ) || 1 );
}
const n = a.length - b.length;
return n && ( ( n>>31 ) || 1 );
}
所以我掉进了这个兔子洞,写了一些测试来建立直觉,结果很奇怪。 简而言之,它看起来像是localeCompare执行了一个小写操作,但等式运算符没有。这导致"ff" >= "ZZ",但localeCompare返回-1,因为"ff" <= 'zz'
为了获得最佳结果,请在浏览器控制台中查看代码日志ctrl + shift + i
第二个片段隐藏了手动测试,因此您可以看到一些随机的测试。
希望这能帮助到某人。
function stringBench(n, bench, min = 10, len = 10, logDif = false) {
function makeid(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() *
charactersLength));
}
return result;
}
var a = [];
var b = [];
var pool = {};
let rle = [];
let rlc = [];
let now;
for (let i = 0; i < n; i++) {
pool[i] = (makeid(min + Math.floor(Math.random() *
len))); //10-20ish
}
for (let i = 0; i < bench; i++) {
a[i] = (Math.floor(Math.random() * n));
b[i] = (Math.floor(Math.random() * n));
}
console.log("now testin le vs lc on a pool of", n, " with this many samples ", bench);
now = Date.now();
for (let i = 0; i < bench; i++) {
rlc[i] = pool[a[i]].localeCompare(pool[b[i]]);
}
let lcDelta = Date.now() - now;
console.log("Performed ", bench, "lc localeCompare in ", lcDelta);
now = Date.now();
for (let i = 0; i < bench; i++) {
rle[i] = pool[a[i]] <= pool[b[i]];
}
let leDelta = Date.now() - now;
console.log("Performed ", bench, "le (<=) compares in ", leDelta)
for (let i = 0; i < n; i++) {
pool[i] = (makeid(min + Math.floor(Math.random() *
len))); //10-20ish
}
for (let i = 0; i < bench; i++) {
a[i] = (Math.floor(Math.random() * n));
b[i] = (Math.floor(Math.random() * n));
}
now = Date.now();
for (let i = 0; i < bench; i++) {
rle[i] = pool[a[i]] <= pool[b[i]];
}
let leDelta2 = Date.now() - now;
console.log("Performed ", bench, "le (<=) compares in ", leDelta2)
now = Date.now();
for (let i = 0; i < bench; i++) {
rlc[i] = pool[a[i]].localeCompare(pool[b[i]]);
}
let lcDelta2 = Date.now() - now;
console.log("Performed ", bench, "lc localeCompare in ", lcDelta2);
function testCmp(a, b, log = true) {
let le = a <= b;
let ge = a >= b;
let lc = a.localeCompare(b);
let l = a < b;
let g = a > b;
if (le && ge) console.assert(lc == 0, 'le && ge -> == -> lc == 0,')
if (le) console.assert(lc <= 0, 'le-> lc <= 0')
if (ge) console.assert(lc >= 0, 'ge-> lc >= 0')
if (l) console.assert(lc < 0, 'l=>lc < 0')
if (g) console.assert(lc > 0, 'g-> lc > 0')
if (!log) return;
console.log(`Compare: ${a} le ${b} `, a <= b);
console.log(`Compare: ${a} ge ${b}`, a >= b);
console.log(`Compare: ${a} lc ${b}`, a.localeCompare(b));
}
let c = 0
for (let i = 0; i < bench; i++) {
if (rle[i] != rlc[i] <= 0) {
c++;
testCmp(pool[a[i]], pool[b[i]], true);
console.warn(pool[a[i]], ' le != lc <= 0 ', pool[b[i]]);
}
// rlc[i] = pool[a[i]].localeCompare(pool[b[i]]);
}
console.warn(' le != lc out of bench, num diffs: ', c);
testCmp('ff', 'ff')
testCmp('ff', 'fa')
testCmp('ff', 'fz')
testCmp('ff', 'fff')
testCmp('ff', 'ffa')
testCmp('ff', 'ffz')
testCmp('ff', 'a')
testCmp('ff', 'z')
testCmp('ff', 'f')
testCmp('ff', 'zff')
testCmp('ff', 'aff')
testCmp('ff', 'ZZ')
testCmp('ff', 'AA')
testCmp('FF', 'ZZ')
testCmp('FF', 'ff')
testCmp('FF', 'AA')
testCmp('ff', 'ZZZ')
console.log("Dif le - lc = ", leDelta2 - lcDelta2);
console.log("avg le ms/Mops = ", (leDelta + leDelta2) / (bench / 1000000));
console.log("avg lc ms/Mops = ", (lcDelta + lcDelta2) / (bench / 1000000));
console.log("Dif - lc = ", leDelta2 - lcDelta2);
};
stringBench(1000, 5000, 1, 3, true);
// stringBench(1000000, 1000000);//nothing is equire
// stringBench(1000, 100000000);
// stringBench(1000000, 100000000, 3, 5);
// stringBench(1000000, 100000000, 15, 20);
function stringBench(n, bench, min = 10, len = 10, logDif = false) {
function makeid(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() *
charactersLength));
}
return result;
}
var a = [];
var b = [];
var pool = {};
let rle = [];
let rlc = [];
let now;
for (let i = 0; i < n; i++) {
pool[i] = (makeid(min + Math.floor(Math.random() *
len))); //10-20ish
}
for (let i = 0; i < bench; i++) {
a[i] = (Math.floor(Math.random() * n));
b[i] = (Math.floor(Math.random() * n));
}
console.log("now testin le vs lc on a pool of", n, " with this many samples ", bench);
now = Date.now();
for (let i = 0; i < bench; i++) {
rlc[i] = pool[a[i]].localeCompare(pool[b[i]]);
}
let lcDelta = Date.now() - now;
console.log("Performed ", bench, "lc localeCompare in ", lcDelta);
now = Date.now();
for (let i = 0; i < bench; i++) {
rle[i] = pool[a[i]] <= pool[b[i]];
}
let leDelta = Date.now() - now;
console.log("Performed ", bench, "le (<=) compares in ", leDelta)
for (let i = 0; i < n; i++) {
pool[i] = (makeid(min + Math.floor(Math.random() *
len))); //10-20ish
}
for (let i = 0; i < bench; i++) {
a[i] = (Math.floor(Math.random() * n));
b[i] = (Math.floor(Math.random() * n));
}
now = Date.now();
for (let i = 0; i < bench; i++) {
rle[i] = pool[a[i]] <= pool[b[i]];
}
let leDelta2 = Date.now() - now;
console.log("Performed ", bench, "le (<=) compares in ", leDelta2)
now = Date.now();
for (let i = 0; i < bench; i++) {
rlc[i] = pool[a[i]].localeCompare(pool[b[i]]);
}
let lcDelta2 = Date.now() - now;
console.log("Performed ", bench, "lc localeCompare in ", lcDelta2);
function testCmp(a, b, log = true) {
let le = a <= b;
let ge = a >= b;
let lc = a.localeCompare(b);
let l = a < b;
let g = a > b;
if (le && ge) console.assert(lc == 0, 'le && ge -> == -> lc == 0,')
if (le) console.assert(lc <= 0, 'le-> lc <= 0')
if (ge) console.assert(lc >= 0, 'ge-> lc >= 0')
if (l) console.assert(lc < 0, 'l=>lc < 0')
if (g) console.assert(lc > 0, 'g-> lc > 0')
if (!log) return;
console.log(`Compare: ${a} le ${b} `, a <= b);
console.log(`Compare: ${a} ge ${b}`, a >= b);
console.log(`Compare: ${a} lc ${b}`, a.localeCompare(b));
}
let c = 0
for (let i = 0; i < bench; i++) {
if (rle[i] != rlc[i] <= 0) {
c++;
testCmp(pool[a[i]], pool[b[i]], true);
console.warn(pool[a[i]], ' le != lc <= 0 ', pool[b[i]]);
}
// rlc[i] = pool[a[i]].localeCompare(pool[b[i]]);
}
console.warn(' le != lc out of bench, num diffs: ', c);
testCmp('ff', 'fa')
testCmp('ff', 'fz')
testCmp('ff', 'ZZ')
console.log("Dif le - lc = ", leDelta2 - lcDelta2);
console.log("avg le ms/Mops = ", (leDelta + leDelta2) / (bench / 1000000));
console.log("avg lc ms/Mops = ", (lcDelta + lcDelta2) / (bench / 1000000));
console.log("Dif - lc = ", leDelta2 - lcDelta2);
// for (let i = 0; i < bench; i++) {
// rlc[i] != rle[i]
// pool[a[i]].localeCompare(pool[b[i]]);
// }
//
// console.log(makeid(5));
};
stringBench(1000, 5000, 1, 3, true);
// stringBench(1000000, 1000000);//nothing is equire
// stringBench(1000, 100000000);
// stringBench(1000000, 100000000, 3, 5);
// stringBench(1000000, 100000000, 15, 20);
String.prototype.strcmp = function(s) {
if (this < s) return -1;
if (this > s) return 1;
return 0;
}
s1.strcmp(s2)