Scala:遍历String的每个字符并使用模式匹配

时间:2018-02-05 19:29:44

标签: string scala char pattern-matching string-iteration

我认为我想做的事情非常明显。对于string1中的每个字符,使用模式匹配打印一些东西。 (我有string2,因为我将使用string1的模式匹配来对字符串2执行某些操作并返回String 2)

出于某种原因,我的代码只打印出"()"。

另外,我如何确保我的代码返回一个String。当我把代码放在终端时,它说:(string1:String)String =>单位,我该怎么说(string1: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 } } } 

但是它会返回一个矢量/字符串列表。我希望所有这些案例都在同一个string2对象上工作。因此,如果我在&#34;你好&#34;上测试方法,它应该返回&#34; OLLEH&#34;。

由于

4 个答案:

答案 0 :(得分:1)

您在yield之后忘记了for ( ... ),因此最后一个for只会运行,抛弃身体内的所有内容,最后返回一个单位()

如果你想要归还某些东西,你应该使用类似的东西:

def stringPipeline(string1: String) = (string2: String) => {
  for (c <- string1) yield {
    c match {
      case 'u' => "Upper Case"
      case 'r' => "reverse"
      case _ => "do something"
    }
  }
}

这将为每个string2提供某种“行动描述列表”。

如果你真的想立即print,你可以这样做:

def stringPipeline(string1: String) = (string2: String) => {
  for (c <- string1) {
    println(c match {
      case 'u' => "Upper Case"
      case 'r' => "reverse"
      case _ => "do something"
    })
  }
}

但现在的方式,它既没有返回任何有意义的东西,也没有任何副作用。

修改

更新:如果您希望将string1视为一系列操作,并将string2视为您要应用这些操作的“材料”,则可以执行以下操作:

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中的每个操作应用于到目前为止累积的所有转换的结果。

答案 1 :(得分:0)

如果你的目标是接收一个在字符串上执行模式的函数,你可以这样做:

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)
}

这个函数返回一个递归函数,它在一个字母之后执行一个字母,最后返回结果字符串。

然后你可以这样做:

val s = "urx"
val fun = stringPipeline(s)
println(fun("hello"))

返回OLLEH

然而,它不是一个迭代,而是一个递归方法(更适合像Scala这样的函数式编程语言)。

答案 2 :(得分:0)

如果将定义粘贴到Scala REPL中,您将看到已定义的函数类型为

stringPipeline: (string1: String)String => Unit

即。一个函数,它接受一个字符串string1作为输入,并返回一个闭包,将第二个字符串string2作为输入,并返回Unit,它与Java中的void类似,只有值{{ 1}}。

那么为什么返回的闭包有()作为返回类型?它的主体只包含一个表达式:

Unit

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" } 中的每个可能的c,然后返回string1。换句话说,()不允许在其中产生值。

如果你想打印字符串&#34;大写&#34;你需要写

for

然后闭包的返回值仍为 case 'u' => println("Upper Case") ,但其评估将打印()表达式中的字符串作为副作用。

另外,如果你不使用它,为什么要引入参数string2?

修改

由于循环内部函数的输出用作循环的下一个循环的输入,因此需要折叠函数,例如:

match

答案 3 :(得分:0)

您需要实现管道,使其折叠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