美文网首页
2020-05-16 5 kyu validDate Regex

2020-05-16 5 kyu validDate Regex

作者: 苦庭 | 来源:发表于2020-05-17 04:50 被阅读0次

    https://www.codewars.com/kata/548db0bd1df5bbf29b0000b7

    My answer / AC

    var validDate = /(?<=\[)((0[13578]\-(0[1-9]|[1-2][0-9]|3[01]))|(1[02]\-(0[1-9]|[1-2][0-9]|3[01]))|(0[469]\-(0[1-9]|[1-2][0-9]|30))|(11\-(0[1-9]|[1-2][0-9]|30))|(02\-(0[1-9]|1[0-9]|2[0-8])))(?=\])/;
    
    

    哪里不好?

    • 为了使用或|大量编组了,实际上会占据不少的内存。优化=将分组变为非捕捉分组,即(expr) -> (?:expr)
    • 31天月份里的10、12月是可以合并到前面的13578月里面的,只要加多一个组,中间加个|即可。30天月份类似。

    Best answer

    var days28 = /02-(0[1-9]|1\d|2[0-8])/
    var days30 = /(?:0[469]|11)-(?:0[1-9]|[12]\d|30)/
    var days31 = /(?:0[13578]|10|12)-(?:0[1-9]|[12]\d|3[01])/
    
    var validDate = new RegExp(
      '\\[(' +
        '(?:' + days28.source + ')|' +
        '(?:' + days30.source + ')|' +
        '(?:' + days31.source + ')' +
      ')\\]'
    )
    

    好在哪里?

    • 分组清晰一目了然
    • 多用非捕捉分组
    • 小知识:正则字面量这个对象只要取它的source属性,就能够得到它的正则字符串表达式。

    Best answer2

    const validDate = /\[(?!(0[2469]|11)-31)(?!02-(29|30))(0[1-9]|1[0-2])-(?!00)([0-2]\d|3[01])\]/;
    

    这个是另外一个我觉得很聪明的写法,能够将非捕捉分组的“AND”特性运用起来。

    • (?:expr) 的意思是:对expr进行匹配,匹配完了,匹配到了(否则当前正则匹配判定为失败,移向下一个匹配点),之后在原来的匹配点接着匹配。"match expr but after that continue matching at the original match-point."
    • 那么(?!expr)的意思是:对expr进行匹配,匹配完了,匹配不到,之后在原来的匹配点接着匹配。

    因此在这个回答中,非捕获分组(?!(0[2469]|11)-31)(?!02-(29|30))不能满足的话才能继续接着匹配,从而达到判断排除不符合天数的月份的目的。

    相关文章

      网友评论

          本文标题:2020-05-16 5 kyu validDate Regex

          本文链接:https://www.haomeiwen.com/subject/foxjohtx.html