如何提取与模式不匹配的字符串部分

时间:2019-03-26 04:49:41

标签: scala pattern-matching

我要提取与模式不匹配的一部分字符串

我的模式匹配条件是字符串长度应为5,并且只能包含N或Y。

例如:

NYYYY => valid

NY    => Invalid , length is invalid

NYYSY => Invalid. character at position 3 is invalid

如果字符串无效,那么我想找出哪个特定字符不匹配。例如:在NYYSY,第4个字符不匹配。

我尝试在Scala中进行模式匹配

val Pattern = "([NY]{5})".r
    paramList match {
     case Pattern(c) => true
     case _  => false
    }

5 个答案:

答案 0 :(得分:2)

返回表明验证状态的String

def validate(str :String, len :Int, cs :Seq[Char]) :String = {
  val checkC = cs.toSet
  val errs = str.zipAll(Range(0,len), 1.toChar, -1).flatMap{ case (c,x) =>
               if      (x < 0)     Some("too long")
               else if (checkC(c)) None
               else if (c == 1)    Some("too short")
               else                Some(s"'$c' at index $x")
             }
  str + ": " + (if (errs.isEmpty) "valid" else errs.distinct.mkString(", "))
}

测试:

validate("NTYYYNN", 4, "NY")  //res0: String = NTYYYNN: 'T' at index 1, too long
validate("NYC",     7, "NY")  //res1: String = NYC: 'C' at index 2, too short
validate("YNYNY",   5, "NY")  //res2: String = YNYNY: valid

答案 1 :(得分:1)

这是一种返回(Char, Int)个无效字符元组及其在给定字符串中的对应位置的列表的方法:

def checkString(validChars: List[Char], validLength: Int, s: String) = {
  val Pattern = s"([${validChars.mkString}]{$validLength})".r

  s match {
    case Pattern(_) => Vector.empty[(Char, Int)]
    case s =>
      val invalidList = s.zipWithIndex.filter{case (c, _) => !validChars.contains(c)}
      if (invalidList.nonEmpty) invalidList else Vector(('\u0000', -1))
  }
}

List("NYYYY", "NY", "NNSYYTN").map(checkString(List('N', 'Y'), 5, _))
// res1: List(Vector(), Vector((?,-1)), Vector((S,2), (T,5)))

如上所示,empty列表表示有效字符串,而(null-char, -1)列表表示字符串具有有效字符但长度无效。

答案 2 :(得分:0)

以下是一条可能适合您需求的建议:

"NYYSY".split("(?<=[^NY])|(?=[^NY])").foreach(println) 

NYY
S
Y

当前一个字符或后一个字符不是YN时,此解决方案会在任意点分割输入字符串。这会将有效和无效字符的每个岛作为单独的行放置在输出中。

答案 3 :(得分:0)

您可以使用其他正则表达式来检测特定问题:

val Pattern = "([NY]{5})".r
val TooLong = "([NY]{5})(.+)".r
val WrongChar = "([NY]*)([^NY].*)".r

paramList match {
  case Pattern(c) => // Good
  case TooLong(head, rest) => // Extra character(s) in sequence
  case WrongChar(head, rest) => // Wrong character in sequence
  case _ => // Too short
}

您可以使用head.length来计算错误的索引,而失败的字符是rest.head

答案 4 :(得分:0)

您可以通过模式匹配字符串的每个字符来实现,而无需使用任何形式的正则表达式或复杂的字符串操作。

def check(value: String): Unit = {
  if(value.length!=5) println(s"$value length is invalid.")
  else value.foldLeft((0, Seq[String]())){
    case (r, char) =>
      char match {
        case 'Y' | 'N' => r._1+1 -> r._2
        case c @ _ => r._1+1 -> {r._2 ++ List(s"Invalid character `$c` in position ${r._1}")}
      }
  }._2 match {
    case Nil => println(s"$value is valid.")
    case errors: List[String] => println(s"$value is invalid - [${errors.mkString(", ")}]")
  }
}

check("NYCNBNY")
NYNYNCC length is invalid.

check("NYCNB")
NYCNB is invalid - [Invalid character `C` in position 2, Invalid character `B` in position 4]

check("NYNNY")
NYNNY is valid.