在 JavaScript 中比较字符串的最佳方法? [复制]
Posted
技术标签:
【中文标题】在 JavaScript 中比较字符串的最佳方法? [复制]【英文标题】:Optimum way to compare strings in JavaScript? [duplicate] 【发布时间】:2011-01-11 04:12:58 【问题描述】:我正在尝试优化一个在 javascript 中对字符串进行二进制搜索的函数。
二分搜索要求您知道键是==
枢轴还是<
枢轴。
但这需要在 JavaScript 中进行两次字符串比较,这与 C
之类的语言不同,后者具有 strcmp()
函数返回三个值 (-1, 0, +1)
(小于、等于、大于)。
在 JavaScript 中是否有这样的原生函数,它可以返回一个三元值,以便在二进制搜索的每次迭代中只需要一次比较?
【问题讨论】:
return str1 < str2 ? -1 : str1 > str2;
?
@1" 这不是最优的;需要两个字符串比较。
在我的机器上它仍然比localeCompare()
快一个数量级(!)。 @Gumbo 的自定义 strcmp()
可能会更快,这取决于字符串相等比较的内部实现的优化程度。
无论如何你都需要两个比较!,一个看是否 a > b 另一个看它们是否相等,javascript 非常快地确定字符串是否相等,因为如果它们相等,它们就是一个并且同一个对象,就像比较两个指针,字符串被“原子化”,存储在哈希表中,所以每个字母组合中,只有一个实例存在。
我建议重新打开此问题,而不是提及有关 strcmp
的问题,即使该问题的答案相同,因为我认为并非所有搜索此问题答案的人都会了解strcmp
。
【参考方案1】:
您可以使用localeCompare()
方法。
string_a.localeCompare(string_b);
/* Expected Returns:
0: exact match
-1: string_a < string_b
1: string_a > string_b
*/
进一步阅读:
MDN: String.prototype.localeCompare Stack Overflow - Is there a JavaScript strcmp()? Tutorials Point: JavaScript String - localeCompare() Method【讨论】:
不幸的是,stringCompare 不可靠。 Opera、IE、Firefox、Chrome 和 Safari 都为 'dog'.localeCompare('cat') 返回 1,这是意料之中的,而当您颠倒调用者和参数时,返回 -1。但是大写字母的行为很奇怪 - 'dog'.localeCompare('Dog') 在我测试的浏览器中,只有 Safar 4 返回 1。它在 IE8 和 firefox 3 中返回 -1,而 Opera 9 和 Chrome 都返回 +32。跨度> 当您需要不区分大小写的比较时,可以使用 toLowerCase 或 toLocaleLowerCase。 我认为重要的是要注意 V8 (Chrome) 在 localeCompare 上对 ECMA-262 的解释似乎与 IE/Firefox 不同。例如:“a”.localeCompare("Z") 应该返回 -1,但返回 7,它是“a”的字符码 - “Z”的字符码。不幸的是,规范中的语言是松散的,指定 localeCompare() 返回负数、正数或 0。(不是特别是 -1、1、0)。我提交了一份错误报告,希望这可能会改变,但自 2010 年 8 月以来一直存在问题,所以我怀疑它会不会。 显然你最好自己比较一下; jsperf.com/localecompare @GerbenJacobs 谢谢。我还从中得出了一个更大的基准(二进制搜索):jsperf.com/localecompare/2【参考方案2】:在 JavaScript 中,您可以检查两个字符串的值是否与整数相同,这样您就可以这样做:
"A" < "B"
"A" == "B"
"A" > "B"
因此,您可以创建自己的函数来检查字符串,其方式与 strcmp()
相同。
所以这将是执行相同操作的函数:
function strcmp(a, b)
return (a<b?-1:(a>b?1:0));
【讨论】:
再次阅读原始问题!关键是要避免进行多个字符串比较。 对不起。没看到...至少这对某人有用。 =|【参考方案3】:您可以use the comparison operators to compare strings。 strcmp
函数可以这样定义:
function strcmp(a, b)
if (a.toString() < b.toString()) return -1;
if (a.toString() > b.toString()) return 1;
return 0;
编辑 这是一个字符串比较函数,最多需要 min length(a), length(b) 个比较来判断如何两个字符串相互关联:
function strcmp(a, b)
a = a.toString(), b = b.toString();
for (var i=0,n=Math.max(a.length, b.length); i<n && a.charAt(i) === b.charAt(i); ++i);
if (i === n) return 0;
return a.charAt(i) > b.charAt(i) ? -1 : 1;
【讨论】:
但是这个例程做了 OP 不想做的事:有两个字符串比较(更不用说那些对“toString”的函数调用了)。 @Pointy:仅进行一次比较是不可能的。您至少需要最少a.length
, b.length
步骤(一次比较两个字符)来确定字符串是否相等。 (即使localeCompare
也会在内部这样做。)
不,localeCompare 不会在内部执行此操作。比较字符是作为减法实现的,因此只要该操作的结果为非零,您就会知道答案。您的答案可能会重新比较 all 每个字符串的字符。
@Pointy:但是减法是逐个字符完成的。这就是重点。这需要 most (至少像我写的那样)min a.length
, b.length
步骤(在两个字符串相等的情况下)。但你是对的。最好先测试是否相等,因为这需要最多的步骤。
@Gumbo localeCompare 不必在 Javascript 中,对吧?它可以本地实现。或者我错过了什么……以上是关于在 JavaScript 中比较字符串的最佳方法? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
在 JavaScript 中将数字转换为字符串的最佳方法是啥?
在 JavaScript 中创建大型静态 DOM 元素的最佳方法?