我有一个字符串数组,我试图过滤包含重复字母的字符串数组。然而,有两件奇怪的事情正在发生,我不明白。这是我的代码:
var array = ["aba", "aab", "baa"];
var pattern = /(\D)\1+/gi;
var filteredArr = array.filter(function(element){
console.log(element);
console.log(pattern.test(element));
return pattern.test(element) != true;
});
console.log(filteredArr);
发生了一些奇怪的事情。在filter函数中,我测试正则表达式是真还是假,并且它应该如此。
pattern.test("aba") = false;
pattern.test("aab") = true;
pattern.test("baa") = true;
但是,如果我在函数之外测试它们,“baa”似乎会返回false ...这很奇怪吧?
console.log(pattern.test("aba")); //returns false
console.log(pattern.test("aab")); //returns true
console.log(pattern.test("baa")); //returns false
进入下一个奇怪的事情。过滤器函数应该返回不通过(即返回false)过滤器测试的元素。我的预期输出是:
filteredArr = ["aba"];
但是,按照代码的方式,我的输出是:
filteredArr = ["aba", "aab", "baa"];
更奇怪的是,如果我更改过滤器函数以返回DO传递的元素(即返回true)测试,则预期的输出将是:
filteredArr = ["aab", "baa"];
但是,我收到的输出是一个空数组:
filteredArr = [];
我非常困惑。我的正则表达式是错误的还是我可能尝试过滤功能无法做到的事情?这是所有代码的小提琴:
答案 0 :(得分:2)
您看到的奇怪行为是g
修饰符的结果。每次调用test
都会提升模式的lastIndex
属性,这使得对test()
的下一次调用从字符串中的稍后点开始。
这是MDN description of the lastIndex
property:
仅当正则表达式实例使用时才设置此属性 “g”标志表示全局搜索。以下规则适用:
- 如果
lastIndex
大于字符串的长度,test()
和exec()
失败,则lastIndex
设置为0
。- 如果
lastIndex
等于字符串的长度,并且正则表达式与空字符串匹配,那么正则表达式 匹配从lastIndex
开始的输入。- 如果
lastIndex
等于字符串的长度,并且正则表达式与空字符串不匹配,那么常规 表达式不匹配输入,lastIndex
重置为0
。- 否则,
lastIndex
将设置为最近一次匹配后的下一个位置。
您可以通过将console.log(pattern.lastIndex);
添加到filter
:
var array = ["aba", "aab", "baa"];
var pattern = /(\D)\1+/gi;
var filteredArr = array.filter(function(element){
var test = pattern.test(element);
console.log(element + ": " + test);
console.log(pattern.lastIndex);
return test;
});
console.log(filteredArr);
要修复代码,请从正则表达式中删除g
标记。
答案 1 :(得分:0)
您正在使用.test
的全局正则表达式,这是有问题的。
考虑以下开发控制台跟踪
$ var pattern = /(\D)\1+/gi;
undefined
$ pattern.lastIndex
0
$ pattern.test('xx')
true
$ pattern.lastIndex
2
$ pattern.test('xx')
false
$ pattern.lastIndex
0
您遇到的问题是在RegExp
处g
标志继续检查lastIndex
,因此如果您连续两次检查相同的字符串,则会得到不同的结果。
您可以手动重置pattern.lastIndex = 0
或使用非全局RegExp
。
答案 2 :(得分:0)
这是一个有效的例子。
var array = ["aba", "aab", "baa","bba","bab"];
var filteredArr = array.filter(function(element){
console.log(element);
//note that a constant is used instead of the var
var t = /(\D)\1+?/gi.test(element);
console.log(t);
return !t;
});
console.log(filteredArr);

您的代码存在问题:
每当您想知道是否在a中找到模式时,请使用test() string(类似于String.prototype.search()方法,区别在于 test()返回一个布尔值,而search()返回索引(或 -1如果没有找到);有关更多信息(但执行速度较慢),请使用exec()方法(类似于String.prototype.match()方法)。如 使用exec()(或与之结合使用),test()多次调用 在同一个全局正则表达式实例将超过 上一场比赛。