使用此正则表达式时,为什么此函数失败?

时间:2017-07-07 15:37:07

标签: javascript regex

我一直在练习使用正则表达式更加舒服,但我很难理解为什么我写的这个函数不起作用。我写了一个简单的函数来计算单词中重复字母的数量,这似乎有时会起作用,但不会一直有效。

function duplicates(str){
    try{
        return str.match(/(.)\1+/ig).length;
    }catch(e){
        return 0;
    }
}

根据我所研究的内容,这个陈述应该通过字符串查找,找到一个不止一次重复忽略大小写的字母(或多个字母),并返回匹配字母的长度。如果没有匹配的字母出现,它将返回0.它适用于某些字符串,但不是全部。这是我得到的:

duplicates("abcdef") -> 0      #should return 0
duplicates("Aabccdef") -> 2    #should return 2
duplicates("Mississippi") -> 3 #should return 3
duplicates("Indivisible") -> 0 #should return 1
duplicates("abcabcabc") -> 0   #should return 3

经过进一步检查,似乎当我运行“Mississippi”时,我得到了预期的数字3,但是当我添加.toString()代替.length时,看看我得到的表达式是什么:

ss,ss,pp

我没有计算,应该有。似乎我也不算“不可分割”,并没有在“abcabcabc”中指出任何重复的字母。它似乎无法计算非连续重复,但我无法弄清楚为什么。我确信这是我对正则表达式如何工作的误解,因为我对他们不熟悉,但如果有人能说明为什么会发生这种情况,那就太棒了!

编辑:有没有办法用RegEx做到这一点,还是我需要使用循环?

4 个答案:

答案 0 :(得分:2)

就您发布的实际正则表达式而言,它存在一些问题。 (.)\1+无法正常工作的原因是“第一次匹配”' (\1)紧跟在匹配组后面跟.。这意味着在密西西比州的情况下,因为没有连续匹配的字母,所以您的模式与它们不匹配。

作为此问题的替代解决方案,您可以保持简单。对于您的用例,更合理的解决方案是简单地遍历并计算每个字母。



function duplicates(str){
    try{
        let letters = str.toLowerCase().split('');
        let countedLetters = {}
        for(let i = 0; i < letters.length; i++) {
            countedLetters[letters[i]] = countedLetters[letters[i]] + 1 || 1;
        }
        return countedLetters;
    } catch(e) {
        return 0;
    }
}

console.log(duplicates('Mississippi'));
&#13;
&#13;
&#13;

答案 1 :(得分:1)

你已经接近实现它了,但是因为你在捕获后立即寻找最近被捕获的角色,你不能计算不是邻居的角色。

这个想法是使用积极的前瞻来找到重复的字符,然后省略重复的字符以留下唯一的字符来计算它们。正则表达式:

(.)(?=.*\1)

ES6:

function duplicates($str) {
    return [...new Set($str.toLowerCase().match(/(.)(?=.*\1)/g))].length;
}

console.log(duplicates("abcdef"));
console.log(duplicates("Aabccdef"));
console.log(duplicates("Mississippi"));
console.log(duplicates("Indivisible"));
console.log(duplicates("abcabcabc"));

ES5:

function _unique(value, index, self) { 
    return self.indexOf(value) === index;
}

function duplicates($str) {
    return ($str.toLowerCase().match(/(.)(?=.*\1)/g) || Array()).filter(_unique).length;
}

console.log(duplicates("abcdef"));
console.log(duplicates("Aabccdef"));
console.log(duplicates("Mississippi"));
console.log(duplicates("Indivisible"));
console.log(duplicates("abcabcabc"));

答案 2 :(得分:0)

你的正则表达式取任何字母,让你说X来自你的单词并且后面引用一个字母来检查它是否相同。您可以使用此可视化工具来了解它正在做什么。它计算第一次出现后紧跟的字符的出现次数。

与您的查询相关联:https://regexper.com/#%2F(.)%5C1%2B%2Fig

链接到网站:https://regexper.com/

答案 3 :(得分:-1)

我没有调查“Indivisible&#39;”中的重复项。

这不是完全答案,因为&#39; abcabcabc&#39;字符串可以划分为子模式,例如&#39; abcabc&#39;从0字符和&#39; abcabc&#39;开始从3个角色开始。

这不是完全答案,但我希望这将是有用的

'olololo'.match(/(.+)(?=(\1))/ig)