使用谓词搜索字符串 - Scala



我很难弄清楚如何使用给定谓词搜索字符串并确定其在字符串中的位置。

def find(x: char => 布尔值): 布尔值 = {

}

例如,如果 x 是 (_ == ' ')

字符串 = "嗨,我的名字是">

它会在计数器上加 2 并返回 true

我猜这就是你想要的...

由于find是一个高阶函数(HOF) - 也就是说,它是一个将函数作为参数的函数 - 它可能需要应用于String实例。谓词(find的函数参数)确定何时找到要查找的字符,find方法报告找到该字符的位置。所以find应该返回一个Option[Int],而不是一个Boolean,这样你就不会丢失有关角色在哪里找到的信息。请注意,您仍可以通过对结果应用.isDefined,将Option[Int]结果更改为Boolean值(true表示搜索成功,false不成功)。

请注意,我已将find重命名为myFind,以避免与内置String.find方法(执行类似的工作)发生冲突。

import scala.annotation.tailrec
// Implicit class cannot be a top-level element, so it's put in an object.
object StringUtils {
// "Decorate" strings with additional functions.
final implicit class MyRichString(val s: String)
extends AnyVal {
// Find a character satisfying predicate p, report position.
def myFind(p: Char => Boolean): Option[Int] = {
// Helper function to keep track of current position.
@tailrec
def currentPos(pos: Int): Option[Int] = {
// If we've passed the end of the string, return None. Didn't find a
// character satisfying predicate.
if(pos >= s.length) None
// Otherwise, if the predicate passes for the current character,
// return position wrapped in Some.
else if(p(s(pos))) Some(pos)
// Otherwise, perform another iteration, looking at the next character.
else currentPos(pos + 1)
}
// Start by looking at the first (0th) character.
currentPos(0)
}
}
}
import StringUtils._
val myString = "hi my name is"
myString.myFind(_ == ' ') // Should report Some(2)
myString.myFind(_ == ' ').isDefined // Should report true
myString.myFind(_ == 'X') // Should report None
myString.myFind(_ == 'X').isDefined // Should report false

如果使用隐式类有点费力,则可以将其实现为将String作为参数的单个函数:

def find(s: String, p: Char => Boolean): Option[Int] = {
// Helper function to keep track of current position.
@tailrec
def currentPos(pos: Int): Option[Int] = {
// If we've passed the end of the string, return None. Didn't find a
// character satisfying predicate.
if(pos >= s.length) None
// Otherwise, if the predicate passes for the current character,
// return position wrapped in Some.
else if(p(s(pos))) Some(pos)
// Otherwise, perform another iteration, looking at the next character.
else currentPos(pos + 1)
}
// Start by looking at the first (0th) character.
currentPos(0)
}
val myString = "hi my name is"
find(myString, _ == ' ') // Should report Some(2)
find(myString, _ == ' ').isDefined // Should report true
find(myString, _ == 'X') // Should report None
find(myString, _ == 'X').isDefined // Should report false

计数器:

"hi my name is".count (_ == 'm')
"hi my name is".toList.filter (_ == 'i').size

布尔:

"hi my name is".toList.exists (_ == 'i')
"hi my name is".contains ('j')

职位:

"hi my name is".zipWithIndex.filter {case (a, b) => a == 'i'}
res8: scala.collection.immutable.IndexedSeq[(Char, Int)] = Vector((i,1), (i,11))

查找的用法:

scala> "hi my name is".find (_ == 'x') 
res27: Option[Char] = None
scala> "hi my name is".find (_ == 's') 
res28: Option[Char] = Some(s)

我建议将字符searchposition分成单独的方法,每个方法都利用String中的内置函数,并包装在implicit class中:

object MyStringOps {
implicit class CharInString(s: String) {
def charPos(c: Char): Int = s.indexOf(c)
def charFind(p: Char => Boolean): Boolean =
s.find(p) match {
case Some(_) => true
case None => false
}
}
}
import MyStringOps._
"hi my name is".charPos(' ')
// res1: Int = 2
"hi my name is".charFind(_ == ' ')
// res2: Boolean = true

最新更新