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


1056

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


25
请参阅新添加的.localeCompare()javascript方法。在撰写本文时(IE11 +)仅受现代浏览器支持。看到developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
阿德里安要


5
@AdrienBe 在Chrome 48控制台中"A".localeCompare( "a" );返回1
manuell '16

3
@manuell表示排序"a"之前"A"。就像"a"以前一样"b"。如果不需要这种行为,则可能需要.toLowerCase()每个字母/字符串。即。"A".toLowerCase().localeCompare( "a".toLowerCase() )看到developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
阿德里安成为

2
因为我想比较通常是一个用于对字符串进行排序/排序的术语。我很久以前在这里评论过。===将检查是否相等,但不足以对字符串进行排序/排序(请参阅我最初链接的问题)。
Adrien

Answers:


1161

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

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

44
转换为大写或小写确实可以在所有语言中提供正确的不区分大小写的比较。 i18nguy.com/unicode/turkish-i18n.html
塞缪尔·内夫

57
@sam:我知道。这就是我写信的原因if you're not worried about special Unicode characters
SLaks 2010年

141
是否有一个理由,更喜欢toUpperCasetoLowerCase
jpmc26 2014年


19
这真的是最好的JS所提供的吗?
库格尔

210

编辑:这个答案最初是9年前添加的。今天,您应该使用localeCompare以下sensitivity: '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'));

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

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

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

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中进行不区分大小写的比较的最佳方法是使用match()带有i标志的RegExp 方法。

不区分大小写的搜索

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

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

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


5
@Quandary,是的,这就是我要说的要处理的内容–“您需要从字符串生成RegExp,但是如果字符串中包含特殊的regex字符,则将字符串传递给RegExp构造函数可能会导致不正确的匹配或失败的匹配”
塞缪尔·内夫

21
对于不区分大小写的字符串比较,使用此方法是最昂贵的解决方案。RegExp用于复杂的模式匹配,因此,它需要为每个模式构建一个决策树,然后针对输入字符串执行决策树。虽然可行,但是这相当于乘坐喷气式飞机去下一个街区购物。tl; dr:请不要这样做。
Agoston Horvath

2
我可以使用localeCompare(),但它返回-1 'a'.localeCompare('A'),就像我在寻找不区分大小写的字符串比较的op一样。
StingyJack

3
@StingyJack使用localeCompare进行不区分大小写的比较,您应该执行'a'.localeCompare('A',undefined,{sensitive:'base'})
Judah Gabriel Himango

1
注:localeCompare版本需要JavaScript引擎支持ECMAScript®国际化API,它是要求做。因此,在依赖它之前,您可能需要检查它是否在所使用的环境中正常工作。例如:const compareInsensitive = "x".localeCompare("X", undefined, {sensitivity: "base"}) === 0 ? (a, b) => a.localeCompare(b, undefined, {sensitivity: "base"}) : (a, b) => a.toLowerCase().localeCompare(b.toLowerCase());或类似的东西。
TJ Crowder

46

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

这是一个简单的例子

'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以获取最新信息。


35

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

(/keyword/i).test(source)

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

(/keyword/).test(source)

17
使用这样的正则表达式将匹配子字符串!在您的示例中,该字符串keyWORD会导致正面匹配。但是字符串this is a keyword yokeywords也将导致正匹配。请注意:-)
Elmer

6
这不能回答问题中要求的相等检查(不区分大小写)!但是,这是一个包含检查!不要使用它
-S.Serpooshan

4
当然,要匹配整个字符串,可以将regexp更改为/^keyword$/.test(source),但是1)如果keyword不是常量,则需要这样做new RegExp('^' + x + '$').test(source); 2)借助regexp来测试诸如不区分大小写的字符串相等性之类的简单操作根本不是很有效。
JHH

28

请记住,大小写是特定于语言环境的操作。根据情况,您可能需要考虑这一点。例如,如果要比较两个人的姓名,则可能要考虑语言环境,但是如果要比较计算机生成的值(例如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;
}

您使用“ !!”是否有原因?执行显式的布尔转换,而不是允许if子句评估值的真实性?
Celos 2014年

不是必需的 我想我是从其他版本的更复杂的代码中获得的。我已经更新了答案。
Shital Shah 2014年

@thekodester您的函数有一个错误。尽管字符串相等,这compareStrings("", "")将给出false事实。
谢尔盖

@Sergey这样做true给我带来了回报。也许这是浏览器的错误?
珍娜·史隆

14

我最近创建了一个微库,提供不区分大小写的字符串帮助器: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

12

如果您担心不等式的方向(也许您想对列表进行排序),则几乎必须进行大小写转换,并且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字母以外的字符串,则结果将很难看。如果不对字符串进行更详细的检查,就无法做很多事情。


7

假设我们要在string变量needle中找到string变量haystack。一共有三个陷阱:

  1. 国际化的应用程序应避免string.toUpperCasestring.toLowerCase。请使用忽略大小写的正则表达式。例如,var needleRegExp = new RegExp(needle, "i");接着是needleRegExp.test(haystack)
  2. 通常,您可能不知道的值needle。注意needle不要包含任何正则表达式特殊字符。使用逃脱这些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
}

你打赌!您所需要做的就是将第new RegExp(...)3行中的零件替换为:new RegExp("^" + needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") + "$", "i");。这可以确保在搜索字符串之前或之后没有其他字符needle
克里斯·谢特

4

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

  1. 将字符串转换为大写,然后使用严格运算符(===)比较它们。严格的运算符对待操作数的方式在以下位置读取内容:http : //www.thesstech.com/javascript/relational-logical-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>

4

这里有很多答案,但我想添加一个基于扩展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");
}


4

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

在JavaScript中,您可以使用它match()来进行字符串比较,不要忘记将其放在iRegEx中。

例:

var matchString = "Test";
if (matchString.match(/test/i)) {
  alert('String matched');
}
else {
 alert('String not matched');
}

1
确保您对部分匹配没问题,否则matchString.match(/^test$/i)
hackel

什么是小写的“ test”而不是小写的“ test”,可以matchString.match(/x/i)工作吗?如果没有,那怎么办?
Razvan Zamfir


3

如果两个字符串都具有相同的已知语言环境,则可能要使用如下Intl.Collator对象:

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

显然,您可能需要缓存以Collator获得更好的效率。

这种方法的优点在于,它应该比使用RegExps快得多,并且基于一组非常可定制的(请参见上文的说明localesoptions构造函数参数)立即可用的整理器。


敏感性的另一种选择是accent,使它不区分大小写,但将aá视为单独的字符。因此baseaccent根据实际需要两者都合适。
马修·克鲁姆利

2

我写了一个扩展名。非常琐碎

if (typeof String.prototype.isEqual!= 'function') {
    String.prototype.isEqual = function (str){
        return this.toUpperCase()==str.toUpperCase();
     };
}

1
试图同时存在两个对String#isEqual如何工作有不同想法的代码库会发生什么?
Ryan Cavanaugh 2013年

3
@KhanSharp许多人认为修改内置类型的原型是一种反模式。这就是为什么人们可能不赞成您的答案的原因。
jt000 2014年

1
偏爱未知的方法定义是否不是考虑周全?例如,一旦某个浏览器决定实施,String#isEqual或者Object#isEqual本机所有页面的行为都不同,并且如果规范不完全符合您的要求,则可能会做一些奇怪的事情。
罗伯特

2

甚至这个问题都已经回答了。我有另一种使用RegExp和match忽略大小写的方法。请参阅我的链接 https://jsfiddle.net/marchdave/7v8bd7dq/27/

$("#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);

  }

1

如何不抛出异常并且不使用慢速正则表达式呢?

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

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

如果要匹配null / undefined,则:

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

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

return (str1 === undefined && str2 === undefined)
    || (str1 === null && str2 === null)
    || (str1 != null && str2 != null 
        && typeof str1 === 'string' && typeof str2 === 'string'
        && str1.toUpperCase() === str2.toUpperCase());

或者只是str1 == str2 || ...
SLaks's

1

由于没有答案明确提供了使用的简单代码段,因此RegExp,我尝试以下方法:

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

它具有几个优点:

  1. 验证参数类型(undefined例如,任何非字符串参数都将使像这样的表达式崩溃str1.toUpperCase())。
  2. 不会遭受可能的国际化问题。
  3. 转义RegExp字符串。

但由于缺少正则表达式转义而遭受痛苦。
Qwertiy

@Qwertiy公平点,每个stackoverflow.com/a/3561711/67824添加了转义。
Ohad Schneider

0

这是一个改进版这个答案

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();
    }
}



用法与测试:


0

将两者都转换为较低值(出于性能原因仅一次),并将它们与三元运算符在一行中进行比较:

function strcasecmp(s1,s2){
    s1=(s1+'').toLowerCase();
    s2=(s2+'').toLowerCase();
    return s1>s2?1:(s1<s2?-1:0);
}

谁说C死了?:D
塞斯(Seth)

0

如果您知道要处理ascii文本,则可以使用大写/小写字符偏移量比较。

只需确保您的“完美”字符串(您要匹配的字符串)的小写字母即可:

const CHARS_IN_BETWEEN = 32;
const LAST_UPPERCASE_CHAR = 90; // Z
function strMatchesIgnoreCase(lowercaseMatch, value) {
    let i = 0, matches = lowercaseMatch.length === value.length;
    while (matches && i < lowercaseMatch.length) {
        const a = lowercaseMatch.charCodeAt(i);
        const A = a - CHARS_IN_BETWEEN;
        const b = value.charCodeAt(i);
        const B = b + ((b > LAST_UPPERCASE_CHAR) ? -CHARS_IN_BETWEEN : CHARS_IN_BETWEEN);
        matches = a === b // lowerA === b
            || A === b // upperA == b
            || a === B // lowerA == ~b
            || A === B; // upperA == ~b
        i++;
    }
    return matches;
}

0

我喜欢这种速记速记变体-

export const equalsIgnoreCase = (str1, str2) => {
    return (!str1 && !str2) || (str1 && str2 && str1.toUpperCase() == str2.toUpperCase())
}

快速处理,并按预期进行。


0

javascript库似乎提供了很多字符串操作。使用起来非常方便

如何安装

npm install --save string

进口

var S = require('string');

Ignorecase比较字符串

var isEqual = S('ignoreCase').equalsIgnoreCase('IGNORECASE')
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.