JavaScript检查字符串中是否包含三个升序字母和数字。

3
我试图找出如何检查字符串中是否有三个升序字母和/或数字。例如,如果一个字符串包含"manabcrt",那么在该字符串中有"abc",或者"castle567"中有"567",或者"castlexyzand789"中有"xyz"和789...所以我想要检查这个。我找到了这个,但它只适用于重复字母。
以下是来自fiddle的代码:
var inputs = [
'helloworld',
'hellloworld',
'aaabc',
'abcddd',
'bbabba'];

var violators = [];
inputs.forEach(function(input) {
if (/(.)\1\1/.test(input)) {
    violators.push(input);
}});
alert("VIOLATORS:\n" + violators.join('\n'));

4
如果你使用正则表达式,很可能会让问题变得过于复杂化。因为这个情况与重复不同,我建议你尝试使用循环。请尝试一下。 - Kaddath
1
是的,只能使用三个字母和/或数字。这是在创建新帐户时进行密码验证的方式。因此,用户不能使用像“castle123”、“javaxyz”或“p456ythonjkl”这样的密码。 - jeewan
1
当您说要一个升序字符序列时,是指它们必须严格地相邻,还是像acd这样的序列也是有效的? - Pedro Corso
是的,“acd”是有效的……唯一的限制是它不能像abc、def、fgh等三个连续字符…我正在尝试使用charCodeAt()方法将其转换为键代码……让我们看看是否起作用。 - jeewan
0123不被允许,890也不被允许。 - jeewan
显示剩余7条评论
6个回答

5

这是一个乏味的练习,但你最好将所有可能的三元组(10 + 2 * 26)在正则表达式中拼写出来,并测试它们是否存在:

(012|123|234|345|456|567|678|789|890|901|abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz|yza|zab|ABC|BCD|CDE|DEF|EFG|FGH|GHI|HIJ|IJK|JKL|KLM|LMN|MNO|NOP|OPQ|PQR|QRS|RST|STU|TUV|UVW|VWX|WXY|XYZ|YZA|ZAB)

当然,这种方法对非拉丁字符无效。
请查看实时演示(Regex101)
要在您的代码中使用它,请替换


if (/(.)\1\1/.test(input)) {
    violators.push(input);
}});

使用

if (/(012|123|234|345|456|567|678|789|890|901|abc|bcd|cde|def|efg|fgh|ghi|hij|ijk|jkl|klm|lmn|mno|nop|opq|pqr|qrs|rst|stu|tuv|uvw|vwx|wxy|xyz|yza|zab|ABC|BCD|CDE|DEF|EFG|FGH|GHI|HIJ|IJK|JKL|KLM|LMN|MNO|NOP|OPQ|PQR|QRS|RST|STU|TUV|UVW|VWX|WXY|XYZ|YZA|ZAB)/.test(input)) {
    violators.push(input);
}});

3
这个问题被标记为“regex”,而这是唯一的正则表达式答案。即使这不是一个漂亮和实际的解决方案,它也是有效的。那么,为什么会有负评呢?(附注:您可以跳过大写字母测试,只需添加“i”标志进行不区分大小写的测试。) - SamWhan
我在谷歌上输入了9 + 2*24,猜猜结果是多少?只有57!看起来一旦写出来就很容易理解,但在现实世界中,Nina惊人的聪明答案(也得到了赞同)需要大量注释,以便其他开发人员(也许)能够理解算法。 - Scott Weaver
@ClasG 感谢您的道义支持 :). 不区分大小写的匹配会标记混合大小写的三元组(如'aBc'),在严格意义上和给定的密码验证上下文中不被视为“升序”。当然,总的来说,您是正确的。 - collapsar

5

您可以通过计算升序对来检查值。

var array = ['manabcrt', 'castle567', , 'castlexyzand789', 'helloworld', 'hellloworld', 'aaabc', 'abcddd', 'bbabba'],
    check = array.filter(s => {
        var v = 1;
        return [...s].some((c, i, a) => {
            v *= parseInt(c, 36) + 1 === parseInt(a[i + 1], 36);
            return ++v === 3;
        });
    });
    
console.log(check);

一些调整针对案例'90'和不包括'9a'。

var array = ['zab', '901', '9ab', 'manabcrt', 'castle567', , 'castlexyzand789', 'helloworld', 'hellloworld', 'aaabc', 'abcddd', 'bbabba'],
    check = array.filter(s => {
        var v = 1;
        return [...s].some((c, i, a) => {
            var l = parseInt(c, 36),
                r = parseInt(a[i + 1], 36);

            v *= l + 1 === r && l !== 9 && r !== 10 || l === 9 && r === 0 || l === 35 && r === 10;
            return ++v === 3;
        });
    });
    
console.log(check);


1
太棒了,你的代码非常好,尤其是在现实世界的例子中使用了36进制! - collapsar

2

通过使用Array.filter()String.charCodeAt()函数:

var inputs = ['manabcrt', 'castle345', 'helloworld', 'abcddd', 'password'],
    invalid_items = inputs.filter(function(w){
        var len = w.length;            // word length
        for (i=0; i<=len-3; i+=3) {    // iterating over 3-char sequences
            var char_code = w[i].charCodeAt(0);
            if (w[i+1].charCodeAt(0) - char_code == 1 &&
                w[i+2].charCodeAt(0) - char_code == 2) {
                return true;
            }
        }
        return false;
    });

console.log(invalid_items);

性能测试结果: 在此输入图片描述


哇,这是一份很不错的分析……有些需要考虑的地方……但我的情况只涉及一小块代码,也许我将创建一个函数来检查连续字母/数字……但是非常感谢你们提供这些信息,我还需要考虑要走哪条路线……两种解决方案对我都很好,所以非常感谢你们所有人。 - jeewan

0

对于任何子字符串长度

function containsNAscLetters(input, n){
    for(var j = 0; j<=input.length-n; j++){
        var buf = input.substring(j, j+n);
        if (buf.split('').sort().join('').toString()===buf) return buf;
    }
    return null;
}

containsNAscLetters("avfabc", 3)

0

不需要太多复杂的操作,你可以使用一个 for 循环来实现,甚至可以处理长度大于3的序列:

function hasAscSequence(str, limit){
  var count = 0;
  for(var i = 1; i<str.length;i++){
    if(str.charCodeAt(i) - str.charCodeAt(i-1) == 1) count++;
    else count = 0;
    if(count == limit-1) return true
  }
  return false;
}

var inputs = [
'helloworld',
'hellloworld',
'aaabc',
'abcddd',
'bbabba'];

console.log(inputs.filter(x=>!hasAscSequence(x, 3)));


0

如果您也不想匹配连续3个降序字符:

let inputs = [
    'helloworld',
    'hellloworld',
    'aaabc',
    'abcddd',
    'bbabba',
    'cbaheop'
  ],
  valid = [];

inputs.forEach((password) => {
  let passValid = true;
    for (i = 0; i < password.length - 2; i++) {
      let currentChar = password.charCodeAt(i),
        oneCharLater = password.charCodeAt(i + 1),
        twoCharLater = password.charCodeAt(i + 2);

      if ((currentChar + 1 === oneCharLater && currentChar + 2 === twoCharLater) || (currentChar - 1 === oneCharLater && currentChar - 2 === twoCharLater)) {
        passValid = false;
        break;
      }
    }
  if (passValid) {
    valid.push(password)
  }
})

console.log(valid)


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