Scala:列表/序列上的正则表达式

Scala:列表/序列上的正则表达式,scala,Scala,是否有一种系统的方法来搜索任意给定序列中的子序列模式?从某种意义上说,它类似于正则表达式,但在元素序列之上 更具体地说,我们希望完成此功能 def findPattern(seq: Seq[String], Seq[String]): Seq[Int] = { // find the indices of seq which matches the input pattern. // if the pattern is not found, return Seq.empty. } 例

是否有一种系统的方法来搜索任意给定序列中的子序列模式?从某种意义上说,它类似于正则表达式,但在元素序列之上

更具体地说,我们希望完成此功能

def findPattern(seq: Seq[String], Seq[String]): Seq[Int] = { 
  // find the indices of seq which matches the input pattern.
  // if the pattern is not found, return Seq.empty.
}
例如,对于以下输入和目标模式:

seq: Seq[String] = Seq("NNS", "VBG", "JJ", "NNS", "IN", "NNP", "NNP")
pattern: String = Seq("VBG", "JJ") 
所需输出应为:

Seq(1, 2)
具有相同
序列的另一个示例:

pattern: String = Seq("VBG", "?", "NNS") 
并且期望的输出应该是

Seq(1, 2, 3)
还有一个例子:

pattern: String = Seq("VBG", "*", "IN") 
这将导致:

Seq(1, 2, 3, 4)

旁注:可以使输出
Seq[Seq[Int]]
适应多个模式的存在

我认为解析器应该对查找匹配模式更有意义,有一个实现,希望对您有所帮助:

  def findPattern(list: List[String], pattern: List[String]): List[List[Int]] = {
    def nextPattern(lt: Option[List[(String, Int)]], ps: List[String]): Option[List[(String, Int)]] = {
      ps match {
        //if only have "*" should return all
        case List("*") => lt
        //filter whether first str match head, if not return None
        case List(head) =>
          lt.filter(_.nonEmpty).filter(_.head._1 == head).map(r => {
            List(r.head)
          })
        //minimum match for wildcard for first str
        case "*" :: List(last) =>
          lt.filter(_.nonEmpty).flatMap(t => {
            t.find(_._1 == last).map(i => {
              t.takeWhile(_._1 != last) :+ i
            })
          })
        case "*" :: last :: l =>
          nextPattern(lt, List("*", last)).flatMap(j => {
            nextPattern(lt.map(_.drop(j.size)), l).map(i => {
              j ++ i
            })
          })
        //skip fist str
        case "?" :: l =>
          lt.filter(_.nonEmpty).flatMap(r => {
            nextPattern(Some(r.tail), l).map(j => {
              r.head :: j
            })
          })
        //match the list first str
        case head :: l =>
          lt.filter(_.nonEmpty).filter(_.head._1 == head).flatMap(r => {
            nextPattern(Some(r.tail), l).map(j => {
              r.head :: j
            })
          })
      }
    }
    //if any is empty, return None
    list.isEmpty || pattern.isEmpty match {
      case true => List.empty
      case false =>
        val relevantIndices = list.zipWithIndex.filter(_._1 == pattern.head).map(_._2)
        val relevantSublists = relevantIndices.map(list.zipWithIndex.drop)
        relevantSublists.map{ sublist =>
          nextPattern(Some(sublist), pattern).map(_.map(_._2))
        }.filter(_.isDefined).map(_.get)
    }
  }
测试:

其结果是:

[info] List(List(0, 1))
[info] List(List(0, 1))
[info] List()
[info] List(List(0, 1, 2))
[info] List(List(1, 2, 3))
[info] List(List(2))
[info] List(List(1, 2, 3, 4))
[info] List(List(1, 2, 3, 4, 5, 6))
[info] List()
[info] List()
[info] List(List(0), List(3))

我一点也不清楚为什么?匹配NNS(以及为什么它与位置0不匹配)或为什么*也与中匹配。你能进一步解释一下吗?如果模式是
Seq(“VBG”,“?”,“NNS”)
,那么它是有意义的然后是一个元素的通配符,
*
表示一个(或零?)或多个。哎呀,这是一个输入错误。修正了。好的,所以你想要一个标准的“glob”样式和一个不同的字母表相匹配。您是否需要在模式中使用文字'*或'?'呢?(也就是说,你是否需要某种形式的逃跑)。一个快速的谷歌搜索结果是:-你需要让它在Seq[A]上工作,不仅仅是字符串,而且看起来很简单。@TheArchetypalPaul的观点很好。正如您所指出的,我们可以为输入定义类型并区分“?”标签和As通配符。很好!这个实施是一个更大项目的一部分吗?@Daniel,不,这个实施是我尝试的。你知道为什么它失败了吗<代码>列表:列表(DT,NN,IN,DT,NNP,NN,VBD,IN,NN,,,DT,NN,NN,VBD,VBN,IN,CD,,,DT,VBG,VBD,NNP,CC,MD,VB,IN,NNP,)模式:列表(IN,NN)
我对代码做了一些小改动,以覆盖一些边缘情况(如上面的示例)和多个模式。你怎么想?是的,你能行。
[info] List(List(0, 1))
[info] List(List(0, 1))
[info] List()
[info] List(List(0, 1, 2))
[info] List(List(1, 2, 3))
[info] List(List(2))
[info] List(List(1, 2, 3, 4))
[info] List(List(1, 2, 3, 4, 5, 6))
[info] List()
[info] List()
[info] List(List(0), List(3))