ChatGPT解决这个技术问题 Extra ChatGPT

如何进行不区分大小写的字符串比较?

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

查看新添加的 .localeCompare() javascript 方法。在撰写本文时仅受现代浏览器支持 (IE11+)。见developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
@AdrienBe "A".localeCompare( "a" ); 在 Chrome 48 控制台中返回 1
@manuell 这意味着在排序时 "a""A" 之前。就像 "a" 出现在 "b" 之前。如果不需要这种行为,可能需要 .toLowerCase() 每个字母/字符串。 IE。 "A".toLowerCase().localeCompare( "a".toLowerCase() )developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
因为我想比较通常是用于排序/排序字符串的术语。我很久以前在这里评论过。 === 将检查是否相等,但不足以对字符串进行排序/排序(参见我最初链接到的问题)。

S
SLaks

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

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

转换为大写或小写确实可以在所有语言中提供正确的不区分大小写的比较。 i18nguy.com/unicode/turkish-i18n.html
@sam:我知道。这就是我写 if you're not worried about special Unicode characters 的原因。
是否有理由更喜欢 toUpperCase 而不是 toLowerCase
@Kugel这个答案是9岁。从那时起就有了新功能,因此截至您发表评论之日,不,这不是 JS 必须提供的最佳功能。请参阅下面关于 localeCompare 的答案,该答案最近更新(但仍是五年前)。我不知道在过去五年中有什么变化会使 localeCompare 不再是最佳答案。
Y
Yves M.

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

function ciEquals(a, b) { return typeof a === 'string' && typeof b === 'string' ? a.localeCompare(b, undefined, { 敏感度: '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 将被视为等效于 á)。

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

Case-insensitive search

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

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

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


@Quandary,是的,这就是我所说的必须处理的内容-“您需要从字符串生成 RegExp,但是如果字符串中包含特殊的正则表达式字符,则将字符串传递给 RegExp 构造函数可能会导致不正确的匹配或匹配失败”
使用这是不区分大小写的字符串比较最昂贵的解决方案。 RegExp 用于复杂的模式匹配,因此,它需要为每个模式构建一个决策树,然后针对输入字符串执行该决策树。虽然它会起作用,但它可以与乘坐喷气式飞机在下一个街区购物。 tl;博士:请不要这样做。
我可以使用 localeCompare(),但它为 'a'.localeCompare('A') 返回 -1,就像我正在寻找不区分大小写的字符串比较的操作一样。
@StingyJack 使用 localeCompare 进行不区分大小写的比较,你应该做 'a'.localeCompare('A', undefined, {sensitive: 'base' })
注意: localeCompare 版本要求 JavaScript 引擎支持 ECMAScript® Internationalization 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()); 或类似的。
D
Dakusan

正如最近的评论中所说,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 是独立的基本字母

灵敏度选项

https://i.stack.imgur.com/tTMud.png

浏览器支持

截至发稿时,适用于 Android 和 Opera Mini 的 UC 浏览器支持 localeoptions 参数。请查看 https://caniuse.com/#search=localeCompare 以获取最新信息。


由于我相当确定浏览器不会定期删除对旧版本功能的支持,因此此处列出的浏览器支持不正确或至少不完整(根据您的 caniuse 链接)。 IE< 11、火狐< 29、铬 < 24, 和 Safari < 10(仅列出流行的浏览器)也不支持 localeoptions 参数,并且很可能在发布此答案时不支持。对于新读者来说,这可能比列出的那些基本上不支持任何现代功能的晦涩浏览器有用得多。
S
Shivam Sharma

更新:

根据评论,先前的答案检查 source contains keyword,使其相等检查添加 ^$

(/^keyword$/i).test(source)

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

(/keyword/i).test(source)

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

(/keyword/).test(source)

使用这样的正则表达式将匹配子字符串!在您的示例中,字符串 keyWORD 将导致肯定匹配。但字符串 this is a keyword yokeywords 也会导致肯定匹配。请注意:-)
这不回答问题中提出的平等检查(不区分大小写)!但是,这是一个包含检查!不要使用它
当然,要匹配整个字符串,可以将正则表达式更改为 /^keyword$/.test(source),但 1) 如果 keyword 不是常量,则需要执行 new RegExp('^' + x + '$').test(source) 和 2) 使用正则表达式来测试某些内容像不区分大小写的字符串相等一样简单,根本不是很有效。
S
Shital Shah

请记住,大小写是特定于语言环境的操作。根据情况,您可能需要考虑到这一点。例如,如果您要比较两个人的姓名,您可能需要考虑语言环境,但如果您要比较机器生成的值(例如 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 子句评估值的真实性?
这不是必需的。我想我是从其他版本的更复杂的代码中得到的。我已经更新了答案。
@thekodester 您的函数有错误。尽管字符串相等,但此 compareStrings("", "") 将给出 false
@Sergey 这样做会为我返回 true。也许这是您的浏览器的错误?
语言环境绝对是一个需要考虑的重要因素。 +1
J
Jasen

如果您担心不等式的方向(也许您想对列表进行排序),则几乎必须进行大小写转换,并且由于 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 字母,则结果排序将很难看。如果不对琴弦进行更详细的检查,则无能为力。


N
Nick Uraltsev

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

C
Chris Chute

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

国际化应用程序应避免使用 string.toUpperCase 和 string.toLowerCase。改用忽略大小写的正则表达式。例如, var needleRegExp = new RegExp(needle, "i");其次是 needleRegExp.test(haystack)。一般来说,您可能不知道针的价值。注意 needle 不包含任何正则表达式特殊字符。使用 needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 转义这些。在其他情况下,如果您想精确匹配 needle 和 haystack,只需忽略大小写,请确保在正则表达式构造函数的开头添加“^”并在末尾添加“$”。

考虑到第 (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
}

你打赌!您只需将第 3 行中的 new RegExp(...) 部分替换为以下内容:new RegExp("^" + needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") + "$", "i");。这可确保您的搜索字符串 needle 之前或之后没有其他字符。
N
Nebulosar

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

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 = "你好"; var b = "你好"; var c = "世界"; 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"); }


x
xxx

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

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

例子:

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

确保您可以接受部分匹配,否则 matchString.match(/^test$/i)
var x = 'test' 不是小写的“test”,matchString.match(/x/i) 会起作用吗?如果没有,什么会起作用?
@RazvanZamfir,如果是动态模式,您可以使用 RegExp Object Ex: var x = new RegExp(/test/, "gi"); matchString.match(x);
const x_regex = new RegExp(`^${x}$`, "gi");,虽然这很混乱。
A
Alexander Abakumov

如果两个字符串都具有相同的已知语言环境,您可能希望像这样使用 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 都可能是合适的。
V
VLAZ

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

将字符串转换为大写,然后使用严格运算符 (===) 进行比较。使用字符串方法进行模式匹配:

使用“搜索”字符串方法进行不区分大小写的搜索。


N
Neetesh Dadwariya

我喜欢这种快速的速记变化——

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

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


J
Jhankar Mahbub

我写了一个扩展。很琐碎

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

两个对 String#isEqual 应该如何工作有不同想法的代码库试图同时存在会发生什么?
@KhanSharp 很多人认为修改内置类型的原型是一种反模式。这就是为什么人们可能会拒绝投票给你的答案。
偏爱未知的方法定义不是考虑不周吗?例如,一旦某些浏览器决定原生实现 String#isEqualObject#isEqual,您的所有页面的行为都会有所不同,并且如果规范与您的规范不完全匹配,则可能会做一些奇怪的事情。
P
Parth Raval
str = 'Lol', str2 = 'lOl', regex = new RegExp('^' + str + '$', 'i');
if (regex.test(str)) {
    console.log("true");
}

x
xxx

甚至这个问题也已经得到了回答。我有一种不同的方法来使用 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);
}

L
Luca C.

将两者都转换为较低的字符串(出于性能原因仅一次)并将它们与内联三元运算符进行比较:

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

谁说C死了? :D
B
Ben Wilde

不抛出异常并且不使用慢正则表达式怎么样?

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

上面的代码片段假设如果字符串为空或未定义,您不想匹配。

如果要匹配 null/undefined,则:

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

如果由于某种原因您关心 undefined vs null:

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 || ...
O
Ohad Schneider

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

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

它有几个优点:

验证参数类型(任何非字符串参数,例如 undefined,都会使 str1.toUpperCase() 等表达式崩溃)。不受可能的国际化问题的影响。转义 RegExp 字符串。


但是缺乏正则表达式转义。
@Qwertiy 公平点,每个 stackoverflow.com/a/3561711/67824 添加了转义。
m
matsko

如果您知道您正在处理 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;
}

P
PHP Guru

为了获得更好的浏览器兼容性,您可以依赖正则表达式。这将适用于过去 20 年发布的所有 Web 浏览器:

String.prototype.equalsci = function(s) {
    var regexp = RegExp("^"+this.replace(/[.\\+*?\[\^\]$(){}=!<>|:-]/g, "\\$&")+"$", "i");
    return regexp.test(s);
}

"PERSON@Ü.EXAMPLE.COM".equalsci("person@ü.example.com")// returns true

这与此处找到的其他答案不同,因为它考虑到并非所有用户都使用现代网络浏览器。

注意:如果您需要支持土耳其语等特殊情况,则需要使用 localeCompare,因为 i 和 I 在土耳其语中不是同一个字母。

"I".localeCompare("i", undefined, { sensitivity:"accent"})===0// returns true
"I".localeCompare("i", "tr", { sensitivity:"accent"})===0// returns false

可能更好地使用 Object.defineProperty 来避免 equalsci 方法是可枚举的。
S
Sergei

这是 this answer改进版

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

用法和测试:

String.equal = function (s1, s2, ignoreCase, useLocale) { if (s1 == null || s2 == null) return false; if (!ignoreCase) { if (s1.length !== s2.length) return false;返回 s1 === s2; } if (useLocale) { if (useLocale.length) return s1.toLocaleLowerCase(useLocale) === s2.toLocaleLowerCase(useLocale) else return s1.toLocaleLowerCase() === s2.toLocaleLowerCase() } else { if (s1.长度!== s2.length) 返回 false;返回 s1.toLowerCase() === s2.toLowerCase(); } } // 如果你不介意扩展原型。 String.prototype.equal = function(string2, ignoreCase, useLocale) { return String.equal(this.valueOf(), string2, ignoreCase, useLocale); } // ------------------ 测试 ---------- console.log("测试..."); console.log('区分大小写 1'); var 结果 = "Abc123".equal("Abc123"); console.assert(结果 === true); console.log('区分大小写 2');结果 = "aBC123".equal("Abc123");控制台.断言(结果 === 假); console.log('忽略大小写');结果 = "AbC123".equal("aBc123", true); console.assert(结果 === true); console.log('忽略大小写 + 当前语言环境');结果 = "AbC123".equal("aBc123", true); console.assert(结果 === true); console.log('Turkish test 1 (ignore case, en-US)');结果 = "IiiiI".equal("ıiİI", true, "en-US");控制台.断言(结果 === 假); console.log('土耳其语测试 2 (忽略大小写,tr-TR)');结果 = "IiiiI".equal("ıiİI", true, "tr-TR"); console.assert(结果 === true); console.log('土耳其语测试 3 (区分大小写,tr-TR)');结果 = "IiiiI".equal("ıiİI", false, "tr-TR");控制台.断言(结果 === 假); console.log('null-test-1');结果 = "AAA".equal(null);控制台.断言(结果 === 假); console.log('null-test-2');结果 = String.equal(null, "BBB");控制台.断言(结果 === 假); console.log('null-test-3');结果 = String.equal(null, null);控制台.断言(结果 === 假);


E
Erfan Taghvaei

我们也可以使用 ASCII 来做到这一点:

function toLower(a){

    let c = "";

    
    for(let i = 0;i<a.length;i++){

        
        let f = a.charCodeAt(i);
        if(f < 95){

            c += String.fromCharCode(f+32);
        }
        else{

            c += a[i];
        }
    }

    return c;
}
function compareIt(a,b){


    return toLower(a)==toLower(b);


}
console.log(compareIt("An ExamPlE" , "an example"));