不区分大小写的字符串比较怎么办?

如何在 JavaScript 中执行不区分大小写的字符串比较?

答案

最简单的方法(如果您不担心特殊的 Unicode 字符)是调用toUpperCase

var areEqual = string1.toUpperCase() === string2.toUpperCase();

编辑 :这个答案最初是 9 年前添加的。今天,您应该将localeComparesensitivity: 'accent'选项结合使用:

function ciEquals(a, b) {
    return typeof a === 'string' && typeof b === 'string'
        ? a.localeCompare(b, undefined, { sensitivity: 'accent' }) === 0
        : a === b;
}

console.log("'a' = 'a'?", ciEquals('a', 'a'));
console.log("'AaA' = 'aAa'?", ciEquals('AaA', 'aAa'));
console.log("'a' = 'á'?", ciEquals('a', 'á'));
console.log("'a' = 'b'?", ciEquals('a', 'b'));

{ sensitivity: 'accent' }告诉localeCompare()将相同基本字母的两个变体视为相同, 除非它们的重音不同(如第三个示例中所示)。

另外,您可以使用{ sensitivity: 'base' } ,只要两个字符的基本字符相同就将它们视为等效(因此A将被视为等同于á )。

请注意 ,在 IE10 或更低版本或某些移动浏览器中不支持localeCompare的第三个参数(请参见上面链接的页面上的兼容性表),因此,如果需要支持这些浏览器,则需要某种后备:

function ciEqualsInner(a, b) {
    return a.localeCompare(b, undefined, { sensitivity: 'accent' }) === 0;
}

function ciEquals(a, b) {
    if (typeof a !== 'string' || typeof b !== 'string') {
        return a === b;
    }

    //      v--- feature detection
    return ciEqualsInner('A', 'a')
        ? ciEqualsInner(a, b)
        : /*  fallback approach here  */;
}

原始答案

在 JavaScript 中进行不区分大小写的比较的最佳方法是使用带有i标志的 RegExp match()方法。

不区分大小写的搜索

当两个被比较的字符串都是变量(不是常量)时,这会稍微复杂一点,因为您需要从字符串生成 RegExp,但是如果字符串具有特殊的 regex,则将字符串传递给 RegExp 构造函数可能会导致不正确的匹配或失败的匹配里面的字符。

如果您关心国际化,请不要使用toLowerCase()toUpperCase()因为它不能在所有语言中提供准确的不区分大小写的比较。

http://www.i18nguy.com/unicode/turkish-i18n.html

借助正则表达式,我们也可以实现。

(/keyword/i).test(source)

/i用于忽略大小写。如果没有必要,我们可以忽略并测试不区分大小写的匹配项,例如

(/keyword/).test(source)

如最近的评论中所述, string::localCompare支持不区分大小写的比较(以及其他强大的功能)。

这是一个简单的例子

'xyz'.localeCompare('XyZ', undefined, { sensitivity: 'base' }); // returns 0

还有可以使用的通用函数

function equalsIgnoringCase(text, other) {
    return text.localeCompare(other, undefined, { sensitivity: 'base' }) === 0;
}

请注意,您可能应该输入要使用的特定语言环境,而不是undefined语言环境。如 MDN 文档中所述,这一点很重要

在瑞典语中,ä 和 a 是单独的基本字母

灵敏度选项

从MDN列出的灵敏度选项

浏览器支持

在发布时,适用于 Android 和 Opera Mini 的 UC 浏览器支持区域设置选项参数。请检查https://caniuse.com/#search=localeCompare以获取最新信息。

请记住,大小写是特定于语言环境的操作。根据情况,您可能需要考虑这一点。例如,如果您要比较两个人的姓名,则可能要考虑语言环境,但是如果要比较计算机生成的值(例如 UUID),则可能不需要。这就是为什么我在 utils 库中使用以下函数的原因(请注意,出于性能原因不包括类型检查)。

function compareStrings (string1, string2, ignoreCase, useLocale) {
    if (ignoreCase) {
        if (useLocale) {
            string1 = string1.toLocaleLowerCase();
            string2 = string2.toLocaleLowerCase();
        }
        else {
            string1 = string1.toLowerCase();
            string2 = string2.toLowerCase();
        }
    }

    return string1 === string2;
}

我最近创建了一个微型库,提供不区分大小写的字符串帮助器: https : //github.com/nickuraltsev/ignore-case 。 (它在内部使用toUpperCase 。)

var ignoreCase = require('ignore-case');

ignoreCase.equals('FOO', 'Foo'); // => true
ignoreCase.startsWith('foobar', 'FOO'); // => true
ignoreCase.endsWith('foobar', 'BaR'); // => true
ignoreCase.includes('AbCd', 'c'); // => true
ignoreCase.indexOf('AbCd', 'c'); // => 2

如果您担心不等式的方向(也许您想对列表进行排序),则几乎必须进行大小写转换,并且由于 Unicode 中的小写字符比大写字符多,因此 toLowerCase 可能是最好的转换方法。

function my_strcasecmp( a, b ) 
{
    if((a+'').toLowerCase() > (b+'').toLowerCase()) return 1  
    if((a+'').toLowerCase() < (b+'').toLowerCase()) return -1
    return 0
}

Javascript 似乎使用语言环境 “C” 进行字符串比较,因此,如果字符串包含 ASCII 字母以外的字符串,则结果将很难看。如果不对字符串进行更详细的检查,就无法做很多事情。

假设我们要在字符串变量haystack找到字符串变量needle 。有三个陷阱:

  1. 国际化的应用程序应避免使用string.toUpperCasestring.toLowerCase 。请使用忽略大小写的正则表达式。例如, var needleRegExp = new RegExp(needle, "i");其次是needleRegExp.test(haystack)
  2. 通常,您可能不知道needle的值。请注意, needle不包含任何正则表达式特殊字符 。使用needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");来转义它们needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
  3. 在其他情况下,如果要精确匹配needlehaystack ,而忽略大小写,请确保在正则表达式构造函数的开头添加"^" ,在结尾添加"$"

考虑到点(1)和(2),示例如下:

var haystack = "A. BAIL. Of. Hay.";
var needle = "bail.";
var needleRegExp = new RegExp(needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), "i");
var result = needleRegExp.test(haystack);
if (result) {
    // Your code here
}

有两种不区分大小写的比较方式:

  1. 将字符串转换为大写,然后使用严格运算符( === )比较它们。严格的运算符对待操作数的方式在以下位置读取内容: http : //www.thesstech.com/javascript/relational-ologic-operators
  2. 使用字符串方法进行模式匹配:

使用 “搜索” 字符串方法进行不区分大小写的搜索。在以下网址了解有关搜索和其他字符串方法的信息: http : //www.thesstech.com/pattern-matching-using-string-methods

<!doctype html>
  <html>
    <head>
      <script>

        // 1st way

        var a = "apple";
        var b = "APPLE";  
        if (a.toUpperCase() === b.toUpperCase()) {
          alert("equal");
        }

        //2nd way

        var a = " Null and void";
        document.write(a.search(/null/i)); 

      </script>
    </head>
</html>

这里有很多答案,但是我想添加一个基于扩展 String lib 的解决方案:

String.prototype.equalIgnoreCase = function(str)
{
    return (str != null 
            && typeof str === 'string'
            && this.toUpperCase() === str.toUpperCase());
}

这样,您可以像在 Java 中一样使用它!

例:

var a = "hello";
var b = "HeLLo";
var c = "world";

if (a.equalIgnoreCase(b)) {
    document.write("a == b");
}
if (a.equalIgnoreCase(c)) {
    document.write("a == c");
}
if (!b.equalIgnoreCase(c)) {
    document.write("b != c");
}

输出将是:

"a == b"
"b != c"

String.prototype.equalIgnoreCase = function(str) {
  return (str != null &&
    typeof str === 'string' &&
    this.toUpperCase() === str.toUpperCase());
}


var a = "hello";
var b = "HeLLo";
var c = "world";

if (a.equalIgnoreCase(b)) {
  document.write("a == b");
  document.write("<br>");
}
if (a.equalIgnoreCase(c)) {
  document.write("a == c");
}
if (!b.equalIgnoreCase(c)) {
  document.write("b != c");
}