javascript不区分大小写的字符串比较

JavaScript case insensitive string comparison

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


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

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


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

1
2
3
4
5
6
7
8
9
10
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的第三个参数(请参见上面链接的页面上的兼容性图表),因此如果需要支持这些浏览器,则需要某种回退:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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中进行不区分大小写比较的最佳方法是使用regexp match()方法和i标志。

不区分大小写搜索

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

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

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


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

1
(/keyword/i).test(source)

/i表示忽略情况。如果不需要,我们可以忽略并测试不区分大小写的匹配,例如

1
(/keyword/).test(source)


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}


正如在最近的评论中所说,string::localCompare支持不区分大小写的比较(以及其他强有力的东西)。

下面是一个简单的例子

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

以及可以使用的通用函数

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

请注意,您应该输入正在使用的特定区域设置,而不是undefined。如MDN文档所示,这一点很重要。

in Swedish, ? and a are separate base letters

灵敏度选项

Sensitivity options tabulated from MDN

浏览器支持

截至发帖时,Android和Opera Mini的UC浏览器不支持区域设置和选项参数。请查看https://canius.com/search=localecompare以获取最新信息。


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

1
2
3
4
5
6
7
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可能是要使用的最佳转换。

1
2
3
4
5
6
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。有三种方法:

  • 国际化应用应避免string.toUpperCasestring.toLowerCase。使用忽略大小写的正则表达式。例如,var needleRegExp = new RegExp(needle,"i");后接needleRegExp.test(haystack)
  • 一般来说,您可能不知道EDOCX1的值(0)。注意,needle不包含任何正则表达式特殊字符。用needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&");逃出这些。
  • 在其他情况下,如果要精确匹配needlehaystack,只需忽略大小写,请确保在正则表达式构造函数的开头添加"^",在结尾添加"$"
  • 考虑到第(1)和(2)点,示例如下:

    1
    2
    3
    4
    5
    6
    7
    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
    }


    区分大小写比较有两种方法:

  • 将字符串转换为大写,然后使用严格运算符(===对其进行比较)。严格的运算符如何处理操作数在以下位置读取内容:http://www.thesstech.com/javascript/relational-logical-operators
  • 使用字符串方法进行模式匹配:
  • 使用"search"字符串方法进行不区分大小写的搜索。阅读搜索和其他字符串方法:http://www.thesstech.com/pattern-matching-using-string-methods

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <!doctype html>
      <html>
        <head>
         

            // 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));

         
        </head>
    </html>

    这里有很多答案,但我喜欢在扩展字符串库的基础上添加解决方案:

    1
    2
    3
    4
    5
    6
    String.prototype.equalIgnoreCase = function(str)
    {
        return (str != null
                && typeof str === 'string'
                && this.toUpperCase() === str.toUpperCase());
    }

    这样你就可以像在爪哇一样使用它了!

    例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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");
    }

    输出将是:

    1
    2
    "a == b"
    "b != c"

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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("");
    }
    if (a.equalIgnoreCase(c)) {
      document.write("a == c");
    }
    if (!b.equalIgnoreCase(c)) {
      document.write("b != c");
    }


    1
    2
    3
    4
    str = 'Lol', str2 = 'lOl', regex = new RegExp('^' + str + '$', 'i');
    if (regex.test(str)) {
        console.log("true");
    }


    不抛出异常和不使用慢速regex怎么样?

    1
    2
    3
    return str1 != null && str2 != null
        && typeof str1 === 'string' && typeof str2 === 'string'
        && str1.toUpperCase() === str2.toUpperCase();

    上面的代码段假定您不希望在字符串为空或未定义时匹配。

    如果要匹配空/未定义,则:

    1
    2
    3
    4
    return (str1 == null && str2 == null)
        || (str1 != null && str2 != null
            && typeof str1 === 'string' && typeof str2 === 'string'
            && str1.toUpperCase() === str2.toUpperCase());

    如果出于某种原因,您关心未定义vs空:

    1
    2
    3
    4
    5
    return (str1 === undefined && str2 === undefined)
        || (str1 === null && str2 === null)
        || (str1 != null && str2 != null
            && typeof str1 === 'string' && typeof str2 === 'string'
            && str1.toUpperCase() === str2.toUpperCase());


    使用regex进行字符串匹配或比较。

    在javascript中,可以使用match()进行字符串比较,别忘了把i放进regex。

    例子:

    1
    2
    3
    4
    5
    6
    7
    var matchString ="Test";
    if (matchString.match(/test/i)) {
      alert('String matched');
    }
    else {
     alert('String not matched');
    }

    我写了一个分机。非常琐碎

    1
    2
    3
    4
    5
    if (typeof String.prototype.isEqual!= 'function') {
        String.prototype.isEqual = function (str){
            return this.toUpperCase()==str.toUpperCase();
         };
    }


    甚至这个问题也已经回答了。我有一个不同的方法来使用regexp和match来忽略区分大小写。请看我的链接https://jsfiddle.net/marchdave/7v8bd7dq/27/

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $("#btnGuess").click(guessWord);

      function guessWord() {

       var letter = $("#guessLetter").val();
       var word = 'ABC';
       var pattern = RegExp(letter, 'gi'); // pattern: /a/gi

       var result = word.match(pattern);
       alert('Ignore case sensitive:' + result);

      }

    由于没有答案清楚地提供了使用RegExp的简单代码片段,下面是我的尝试:

    1
    2
    3
    4
    5
    function compareInsensitive(str1, str2){
      return typeof str1 === 'string' &&
        typeof str2 === 'string' &&
        new RegExp("^" + str1.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') +"$","i").test(str2);
    }

    它有几个优点:

  • 验证参数类型(例如,任何非字符串参数,如undefined,都会破坏像str1.toUpperCase()这样的表达式)。
  • 不存在可能的国际化问题。
  • 退出RegExp字符串。

  • 如果两个字符串具有相同的已知区域设置,您可能希望使用这样的Intl.Collator对象:

    1
    2
    3
    function equalIgnoreCase(s1: string, s2: string) {
        return new Intl.Collator("en-US", { sensitivity:"base" }).compare(s1, s2) === 0;
    }

    显然,为了提高效率,您可能需要缓存Collator

    这种方法的优点是,它应该比使用regexps快得多,并且基于一组非常可定制的现成的collator(参见上文中对localesoptions构造函数参数的描述)。


    这是此答案的改进版本。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    String.equal = function (s1, s2, ignoreCase, useLocale) {
        if (s1 == null || s2 == null)
            return false;

        if (!ignoreCase) {
            if (s1.length !== s2.length)
                return false;

            return s1 === s2;
        }

        if (useLocale) {
            if (useLocale.length)
                return s1.toLocaleLowerCase(useLocale) === s2.toLocaleLowerCase(useLocale)
            else
                return s1.toLocaleLowerCase() === s2.toLocaleLowerCase()
        }
        else {
            if (s1.length !== s2.length)
                return false;

            return s1.toLowerCase() === s2.toLowerCase();
        }
    }

    < BR>


    用途和测试:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    String.equal = function (s1, s2, ignoreCase, useLocale) {
        if (s1 == null || s2 == null)
            return false;

        if (!ignoreCase) {
            if (s1.length !== s2.length)
                return false;

            return s1 === s2;
        }

        if (useLocale) {
            if (useLocale.length)
                return s1.toLocaleLowerCase(useLocale) === s2.toLocaleLowerCase(useLocale)
            else
                return s1.toLocaleLowerCase() === s2.toLocaleLowerCase()
        }
        else {
            if (s1.length !== s2.length)
                return false;

            return s1.toLowerCase() === s2.toLowerCase();
        }
    }

    // If you don't mind extending the prototype.
    String.prototype.equal = function(string2, ignoreCase, useLocale) {
      return String.equal(this.valueOf(), string2, ignoreCase, useLocale);
    }

    // ------------------ TESTS ----------------------
    console.log("Tests...");

    console.log('Case sensitive 1');
    var result ="Abc123".equal("Abc123");
    console.assert(result === true);

    console.log('Case sensitive 2');
    result ="aBC123".equal("Abc123");
    console.assert(result === false);

    console.log('Ignore case');
    result ="AbC123".equal("aBc123", true);
    console.assert(result === true);

    console.log('Ignore case + Current locale');
    result ="AbC123".equal("aBc123", true);
    console.assert(result === true);

    console.log('Turkish test 1 (ignore case, en-US)');
    result ="IiiI".equal("?i?I", true,"en-US");
    console.assert(result === false);

    console.log('Turkish test 2 (ignore case, tr-TR)');
    result ="IiiI".equal("?i?I", true,"tr-TR");
    console.assert(result === true);

    console.log('Turkish test 3 (case sensitive, tr-TR)');
    result ="IiiI".equal("?i?I", false,"tr-TR");
    console.assert(result === false);

    console.log('null-test-1');
    result ="AAA".equal(null);
    console.assert(result === false);

    console.log('null-test-2');
    result = String.equal(null,"BBB");
    console.assert(result === false);

    console.log('null-test-3');
    result = String.equal(null, null);
    console.assert(result === false);