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

IT技术 javascript string
2021-01-09 03:24:40

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

6个回答

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

var areEqual = string1.toUpperCase() === string2.toUpperCase();
转换为大写或小写确实可以在所有语言中提供正确的不区分大小写的比较。 i18nguy.com/unicode/turkish-i18n.html
2021-03-10 03:24:40
@Kugel 这个答案已有 9 年历史。从那时起就有了新功能,因此截至您发表评论的日期,不,它不是 JS 必须提供的最佳功能。请参阅下面有关localeCompare最近更新的答案(但仍然是五年前)。我不知道在过去五年中发生了什么变化而localeCompare不再是最佳答案。
2021-03-18 03:24:40
@sam:我知道。这就是我写的原因if you're not worried about special Unicode characters
2021-03-26 03:24:40
是否有一个理由,更喜欢toUpperCasetoLowerCase
2021-03-30 03:24:40

编辑:这个答案最初是在 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'));

{ sensitivity: 'accent' }告诉localeCompare()治疗相同基础函作为相同的两个变体,除非以上它们具有不同的重音符号(如在第三示例)。

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

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

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,但是如果字符串具有特殊的正则表达式,将字符串传递给 RegExp 构造函数可能会导致不正确的匹配或失败的匹配其中的字符。

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

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

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

正如最近的评论中所说,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以获取最新信息。

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

更新:

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

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

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

(/keyword/i).test(source)

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

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

请记住,大小写是特定于语言环境的操作。根据您的情况,您可能希望将其考虑在内。例如,如果您正在比较两个人的姓名,您可能需要考虑语言环境,但如果您正在比较机器生成的值(如 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;
}
@Sergey 这样做会true为我带来回报也许这是您的浏览器的错误?
2021-03-13 03:24:40
你有什么理由使用“!!” 执行显式布尔转换,而不是允许 if 子句评估值的真实性?
2021-03-15 03:24:40
@thekodester 你的函数有一个错误。compareStrings("", "")将给false尽管事实上字符串相等。
2021-03-21 03:24:40
这不是必需的。我想我从其他版本的更复杂的代码中得到了它。我已经更新了答案。
2021-03-31 03:24:40
语言环境绝对是一个需要考虑的重要因素。+1
2021-03-31 03:24:40