JavaScript includes()不区分大小写

161
我有一个字符串数组,需要循环遍历并与另一个传入的字符串进行比较。
var filterstrings = ['firststring','secondstring','thridstring'];
var passedinstring = localStorage.getItem("passedinstring");

for (i = 0; i < filterstrings.lines.length; i++) {
    if (passedinstring.includes(filterstrings[i])) {
        alert("string detected");
    }
}

如果var passedinstring中包含类似于FirsTsTriNgfiRSTStrING的字符串,当进行过滤时如何确保不区分大小写(最好使用正则表达式)?


使用一个常见的情况或创建一个正则表达式,然后与.some一起使用。 - Rajesh
9
不应将此标记为重复。使用“includes”而不是正则表达式的优点在于它涵盖了字符串包含正则表达式特殊字符的情况。 - Joao
11个回答

102
你可以先从filterstrings创建一个RegExp
var filterstrings = ['firststring','secondstring','thirdstring'];
var regex = new RegExp( filterstrings.join( "|" ), "i");

然后测试是否存在传入的字符串
var isAvailable = regex.test( passedinstring );

这是一个测试实现:

// Take care to escape these strings!
// If they are user-input or may contain special regex characters (such as "$" or "."), they have to be escaped.
var filterStrings = ['one','two','three'];
var regex = new RegExp(filterStrings.join( "|" ), "i");

var sentences = [
  "one", // true
  "OnE", // true
  "a rabbit", // false
  "and then two rabbits", // true
  "standing", // false
  "prone", // true
  "AoNeAtWo", // true
];
sentences.forEach(sentence => {
  console.log(
    regex.test(sentence) ? '✅ match:' : '❌ not a match:',
    "'" + sentence + "'",
    );
});


7
请注意,"firststringtest" 在这里也会返回true。在ES5中,filterstrings.map((a) => { return a.toLowerCase() }).includes(passedinstring.toLowerCase()) 可能是解决此问题的方法。 - Jacob Morris
6
如果不对 filterstrings 进行转义,你就有可能得到一个损坏的正则表达式,或者一个具有意外行为的正则表达式。 - Matteo Italia
这个相比于.includes()慢多少? - trainoasis
11
这个答案不应该被接受!如果有人在寻找答案时看到这个答案,请注意!它会对任何可以在数组中找到的子序列返回 truenew RegExp([1,2,3].join("|"), "i").test(12) // true!!! ["Hello","World"].includes("HelloWorld") // false new RegExp(["Hello", "World"].join("|"), "i").test("HelloWorld") // true!!!``` - Tzahi Leh
3
将随机字符串映射到正则表达式模式并不是一个好主意,除非你确实知道这些字符串不包含特殊字符。 - Robo Robok
显示剩余6条评论

75

使用ES6数组方法filter()可以将解决方案简化为单行代码。结合includes()方法判断数组中是否包含某个特定值,再使用toLowerCase()方法将其转换为小写。

var filterstrings = ['firststring','secondstring','thridstring'];
var passedinstring = localStorage.getItem("passedinstring");

// convert each string from filterstrings and passedinstring to lowercase
// to avoid case sensitive issue.
filteredStrings = filterstrings.filter((str) => str.toLowerCase().includes(passedinstring.toLowerCase())

2
这是个很好的答案!这是一个非常简单的单行解决方案。我在过滤器中使用了“filteredStrings”行,然后在封装的过滤语句中只需检查长度是否大于0即可。 - Jan
3
谢谢 - 当人们用最新的功能回答旧问题时,总是让人感激! - codingbryan
2
使用 localeCompare() 会更安全。只使用 .toLowerCase() 存在问题 - 请参考 Jon Skeet 在 YouTube 上的演讲 Back to basics: the mess we've made of our fundamental data types 以了解更多信息。 - Andrew Morton
2
我使用了这个变体: filteredstrings = filterstrings.some(e => e.toUpperCase().includes(activeSearch.toUpperCase())) - CosetteN

66

你可以简单地将传入的字符串转换为小写。

var passedinstring = localStorage.getItem("passedinstring").toLowerCase();

7
好的,在给定的情况下它可以工作,但我想我们也希望它能反过来工作...(即筛选后的字符串也具有大写字母)。 - romainm
6
如果你希望另一种方法也能起作用,那么同样在输入的字符串上使用 toLowerCase()。 - Lengo

30

你可以使用.some方法替换.includes,它返回一个布尔值。
一旦找到匹配项,它就会立即退出,这对于大型数组的性能非常好:

.some(item => item.toLowerCase() == lookup.toLowerCase())

演示:

var arr = ['foo','bar','bar'];
var lookup = "bAr";

// case-sensetive
console.log( arr.includes(lookup) )

// case-insensetive without caring about the type
console.log( arr.some(x => x.toLowerCase() == lookup.toLowerCase()) ) 


或者使用一个独特的名称定义自己的 Array 原型方法:


// the name ("_includes") should be unique enough not to ever be overriten 
// by future language updates or 3rd-party scripts
Array.prototype._includes = function(target){ 
  return this.some(x => x.toLowerCase() == (target||'').toLowerCase()) 
}

console.log( 
  ['foo', 'bar', 'bar']._includes("bAr") 
)


3
如果你在循环外部执行 lookup.toLowerCase(),性能会更好。 - Tomas Loksa
@TomášLokša - 我倾向于提供最简单的解决方案,而由复制粘贴者根据自己的需求进行调整。这里的许多答案可以很容易地改进,但可能并不适合每个人或使解决方案在快速浏览时更难理解,我希望在某些情况下避免这种情况。 - vsync
啊,我明白了 :) 无论如何,感谢你的解决方案,对我非常有用。 - Tomas Loksa
同意Tomas的观点。循环不变量是一种重要的概念。 - undefined

14

将filterstring和passedinstring转换为小写并进行比较

var filterstrings = ['firststring','secondstring','thridstring'];
var passedinstring = 
localStorage.getItem("passedinstring").toLowerCase();

for (i = 0; i < filterstrings.lines.length; i++) {
   if (passedinstring.includes(filterstrings[i].toLowerCase())) {
       alert("string detected");
   }
}

11

使用 toLowerCase() 解决了大小写问题。它把所有的 字符串 转换为小写。

var product=productList.filter((x) => 
x.Name.toLowerCase().includes(("Active").toLowerCase()))

5

我常常在SQL中做的是将两个大写进行比较,或者将两个小写进行比较。为了实现这一点,需要将两侧都进行转换:

    var filterstrings = ['firststring','secondstring','thirDstrIng'];
    var passedinstring =  'ThIrDsTrInG3';
    
    //used for of just to make it more readable
    for (filterstring of filterstrings) {
        if (passedinstring.toUpperCase().includes(filterstring.toUpperCase())) {
            alert("string detected");
        }
    
    }


提示 detected 字符串

啊哈,这很聪明。我以为.includes()只能应用于数组。我看到它也可以应用于字符串了(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes)。 - Rounin

3
我相信这样做会更简单、更短,也更易懂。
  const q = new RegExp(query, 'i');

  filteredUsers = users.filter((user: User) => {
    return (
      user.entity.short.match(q) ||
      user.firstname.match(q) ||
      user.lastname.match(q)
    );
  });

这似乎是在过滤不同的数据集...并假设“查询”不会包含任何具有正则表达式中特殊含义的字符。 - Quentin

2
var filterstrings = ['firststring','secondstring','thridstring'];
var passedinstring = localStorage.getItem("passedinstring");

filterstrings.filter(item => item.name.toLowerCase().includes(passedinstring.toLowerCase()))

3
你的解决方案与此解决方案非常相似:https://dev59.com/LVYM5IYBdhLWcg3w-Dxf#63030383,只是将 (str) => str.toLowerCase()... 替换为 item => item.name.toLowerCase()...。你能解释一下这个差异会带来什么变化,以及为什么你认为这是一个改进的解决方案吗? - joanis

1

一种非正则表达式的方法:

我昨天遇到了这个问题。

我有两个数组,它们都没有包含一致的大小写格式值:

let availableDays = [

  'tuesday',
  'THURSDAY',
  'Monday'
];

let orderedWeekdays = [
  
  'Monday',
  'Tuesday',
  'Wednesday',
  'Thursday',
  'FRIDAY'
]

我需要以不区分大小写的方式找出 orderedWeekdays 中哪些项目存在于 availableDays


解决方案:

我的非正则表达式方法是,首先创建一个新的 array 用于检查:

let availableDays_CheckingArray = availableDays.map((day) => day.toLowerCase());

然后循环遍历orderedWeekdays,每次在比较之前应用.toLowerCase()转换:

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

  if (availableDays_CheckingArray.includes(orderedWeekdays[i].toLowerCase())) {

    [... CODE HERE...]
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接