Scala:遍历字符串的每个字符并使用模式匹配
Scala: iterate through every character of a String and use pattern matching
我想我想做的事情很明显。对于 string1 中的每个字符,使用模式匹配打印一些内容。 (我在那里有 string2,因为我将使用 string1 的模式匹配对字符串 2 和 return 字符串 2 做一些事情)
出于某种原因,我的代码只打印出“()”。
另外,我如何确保我的代码 return 是一个字符串。当我把代码放在终端时,它说: (string1: String)String => Unit ,我怎么让它说 (string1: String)String => String
def stringPipeline(string1: String) = (string2: String) => {
for(c <- string1) {
c match {
case 'u' => "Upper Case"
case 'r' => "reverse"
case _ => "do something"
}
}
}
编辑:
我只想指出我想用 string2 做什么:
def stringPipeline(string1: String) = (string2: String) => {
for(c <- string1) yield {
c match {
case 'U' => string2.toUpperCase
case 'r' => string2.reverse } } }
但它是 return 一个 vector/list 字符串。我希望所有这些情况都适用于同一个 string2 对象。因此,如果我在 "hello" 上测试该方法,它应该 return "OLLEH".
谢谢
你忘记了 for ( ... )
之后的 yield
,因此最后一个 for
简单地运行,扔掉体内的所有东西,最后 return 是一个单元 ()
.
如果你想return一些东西,你应该使用这样的东西:
def stringPipeline(string1: String) = (string2: String) => {
for (c <- string1) yield {
c match {
case 'u' => "Upper Case"
case 'r' => "reverse"
case _ => "do something"
}
}
}
这将为每个 string2
提供某种 "list of action descriptions"。
如果你真的想print
立即做某事,你可以这样做:
def stringPipeline(string1: String) = (string2: String) => {
for (c <- string1) {
println(c match {
case 'u' => "Upper Case"
case 'r' => "reverse"
case _ => "do something"
})
}
}
但现在这样,return既没有任何意义,也没有任何副作用。
编辑:
更新:如果您想将 string1
视为一系列操作,将 string2
视为您要应用这些操作的 "material",您可以这样做:
def stringPipeline(string1: String) = (string2: String) => {
string1.foldLeft(string2) {
case (s, 'u') => s.toUpperCase
case (s, 'r') => s.reverse
case (_, x) =>
throw new Error("undefined string manipulation: " + x)
}
}
以上代码执行以下操作:它从 string2
开始,然后将 string1
中的每个操作应用于迄今为止累积的所有转换的结果。
如果您的目标是接收一个对字符串执行模式的函数,您可以这样做:
def stringPipeline(pattern : String) = {
def handleString(s : String, restPattern : List[Char]) : String = {
restPattern match{
case hd :: tl => {
hd match{
case 'u' => handleString(s.toUpperCase(), tl)
case 'r' => handleString(s.reverse, tl)
case _ => handleString(s, tl)
}
}
case Nil => s
}
}
s : String => handleString(s, pattern.toList)
}
这个函数returns一个递归函数,一个接一个地执行模式的一个字母,最后returns结果字符串。
然后你可以做类似的事情:
val s = "urx"
val fun = stringPipeline(s)
println(fun("hello"))
哪个returnsOLLEH
但是,它不是一种迭代方法,而是一种递归方法(更适合像 Scala 这样的函数式编程语言)。
如果您将定义粘贴到 Scala REPL 中,您将看到您定义的函数类型是
stringPipeline: (string1: String)String => Unit
即一个函数,它以字符串 string1
作为输入,return 是一个以第二个字符串 string2 作为输入的闭包,并且 returning Unit
,就像 void
在 Java 中并且只有值 ()
.
那么为什么 returned 闭包有 Unit
作为 return 类型?它的正文只包含一个表达式:
for(c <- string1) {
c match {
case 'u' => "Upper Case"
case 'r' => "reverse"
case _ => "do something"
}
}
for
计算其内部表达式
c match {
case 'u' => "Upper Case"
case 'r' => "reverse"
case _ => "do something"
}
对于 string1
中的每个可能的 c
,然后 returns ()
。换句话说,for
不让内部产生的值通过。
如果你想打印字符串"Upper Case"你需要写
case 'u' => println("Upper Case")
那么闭包的 return 值仍将是 ()
,但它的计算将打印 match
表达式中的字符串作为副作用。
附带说明一下,如果不使用参数 string2 为什么要引入它?
编辑
由于循环内函数的输出用作循环的下一个循环的输入,因此您需要一个折叠函数,即像这样的东西:
def stringPipeline(string1: String) = (string2: String) => {
string1.foldLeft(string2)((s: String, c: Char) =>
c match {
case 'u' => s.toUpperCase
case 'r' => s.reverse
case _ => s
}
)
}
您需要实现管道,使其折叠 ops
字符串的字符,每个字符都是管道中的一个转换阶段。
您从 input
字符串开始第一次折叠,然后 ops
字符串的每个后续折叠将转换最后一次折叠的输出。
现在,折叠ops
字符串时,只需要在遇到不同的字符时添加不同的变换操作即可。
def stringPipeline(ops: String) = (input: String) => {
ops.toLowerCase.foldLeft(input)((str: String, op: Char) => op match {
case 'u' =>
println("Operator - 'u' :: Transforming - Upper Case")
str.toUpperCase
case 'r' =>
println("Operator - 'r' :: Transforming - Reverse")
str.reverse
case _ =>
println("Operator - 'unknown' :: Doing Nothing")
str
})
}
val pipeline1 = stringPipeline("ur")
val s1 = "abcde"
val s1p1 = pipeline1(s1)
// Operator - 'u' :: Transforming - Upper Case
// Operator - 'r' :: Transforming - Reverse
// s1p1: String = EDCBA
我想我想做的事情很明显。对于 string1 中的每个字符,使用模式匹配打印一些内容。 (我在那里有 string2,因为我将使用 string1 的模式匹配对字符串 2 和 return 字符串 2 做一些事情)
出于某种原因,我的代码只打印出“()”。
另外,我如何确保我的代码 return 是一个字符串。当我把代码放在终端时,它说: (string1: String)String => Unit ,我怎么让它说 (string1: String)String => String
def stringPipeline(string1: String) = (string2: String) => {
for(c <- string1) {
c match {
case 'u' => "Upper Case"
case 'r' => "reverse"
case _ => "do something"
}
}
}
编辑:
我只想指出我想用 string2 做什么:
def stringPipeline(string1: String) = (string2: String) => {
for(c <- string1) yield {
c match {
case 'U' => string2.toUpperCase
case 'r' => string2.reverse } } }
但它是 return 一个 vector/list 字符串。我希望所有这些情况都适用于同一个 string2 对象。因此,如果我在 "hello" 上测试该方法,它应该 return "OLLEH".
谢谢
你忘记了 for ( ... )
之后的 yield
,因此最后一个 for
简单地运行,扔掉体内的所有东西,最后 return 是一个单元 ()
.
如果你想return一些东西,你应该使用这样的东西:
def stringPipeline(string1: String) = (string2: String) => {
for (c <- string1) yield {
c match {
case 'u' => "Upper Case"
case 'r' => "reverse"
case _ => "do something"
}
}
}
这将为每个 string2
提供某种 "list of action descriptions"。
如果你真的想print
立即做某事,你可以这样做:
def stringPipeline(string1: String) = (string2: String) => {
for (c <- string1) {
println(c match {
case 'u' => "Upper Case"
case 'r' => "reverse"
case _ => "do something"
})
}
}
但现在这样,return既没有任何意义,也没有任何副作用。
编辑:
更新:如果您想将 string1
视为一系列操作,将 string2
视为您要应用这些操作的 "material",您可以这样做:
def stringPipeline(string1: String) = (string2: String) => {
string1.foldLeft(string2) {
case (s, 'u') => s.toUpperCase
case (s, 'r') => s.reverse
case (_, x) =>
throw new Error("undefined string manipulation: " + x)
}
}
以上代码执行以下操作:它从 string2
开始,然后将 string1
中的每个操作应用于迄今为止累积的所有转换的结果。
如果您的目标是接收一个对字符串执行模式的函数,您可以这样做:
def stringPipeline(pattern : String) = {
def handleString(s : String, restPattern : List[Char]) : String = {
restPattern match{
case hd :: tl => {
hd match{
case 'u' => handleString(s.toUpperCase(), tl)
case 'r' => handleString(s.reverse, tl)
case _ => handleString(s, tl)
}
}
case Nil => s
}
}
s : String => handleString(s, pattern.toList)
}
这个函数returns一个递归函数,一个接一个地执行模式的一个字母,最后returns结果字符串。
然后你可以做类似的事情:
val s = "urx"
val fun = stringPipeline(s)
println(fun("hello"))
哪个returnsOLLEH
但是,它不是一种迭代方法,而是一种递归方法(更适合像 Scala 这样的函数式编程语言)。
如果您将定义粘贴到 Scala REPL 中,您将看到您定义的函数类型是
stringPipeline: (string1: String)String => Unit
即一个函数,它以字符串 string1
作为输入,return 是一个以第二个字符串 string2 作为输入的闭包,并且 returning Unit
,就像 void
在 Java 中并且只有值 ()
.
那么为什么 returned 闭包有 Unit
作为 return 类型?它的正文只包含一个表达式:
for(c <- string1) {
c match {
case 'u' => "Upper Case"
case 'r' => "reverse"
case _ => "do something"
}
}
for
计算其内部表达式
c match {
case 'u' => "Upper Case"
case 'r' => "reverse"
case _ => "do something"
}
对于 string1
中的每个可能的 c
,然后 returns ()
。换句话说,for
不让内部产生的值通过。
如果你想打印字符串"Upper Case"你需要写
case 'u' => println("Upper Case")
那么闭包的 return 值仍将是 ()
,但它的计算将打印 match
表达式中的字符串作为副作用。
附带说明一下,如果不使用参数 string2 为什么要引入它?
编辑
由于循环内函数的输出用作循环的下一个循环的输入,因此您需要一个折叠函数,即像这样的东西:
def stringPipeline(string1: String) = (string2: String) => {
string1.foldLeft(string2)((s: String, c: Char) =>
c match {
case 'u' => s.toUpperCase
case 'r' => s.reverse
case _ => s
}
)
}
您需要实现管道,使其折叠 ops
字符串的字符,每个字符都是管道中的一个转换阶段。
您从 input
字符串开始第一次折叠,然后 ops
字符串的每个后续折叠将转换最后一次折叠的输出。
现在,折叠ops
字符串时,只需要在遇到不同的字符时添加不同的变换操作即可。
def stringPipeline(ops: String) = (input: String) => {
ops.toLowerCase.foldLeft(input)((str: String, op: Char) => op match {
case 'u' =>
println("Operator - 'u' :: Transforming - Upper Case")
str.toUpperCase
case 'r' =>
println("Operator - 'r' :: Transforming - Reverse")
str.reverse
case _ =>
println("Operator - 'unknown' :: Doing Nothing")
str
})
}
val pipeline1 = stringPipeline("ur")
val s1 = "abcde"
val s1p1 = pipeline1(s1)
// Operator - 'u' :: Transforming - Upper Case
// Operator - 'r' :: Transforming - Reverse
// s1p1: String = EDCBA