1

我认为我想要做的很明显。对于 string1 中的每个字符,使用模式匹配打印一些内容。(我在那里有 string2,因为我将使用 string1 的模式匹配对字符串 2 做一些事情并返回字符串 2)

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

另外我如何确保我的代码返回一个字符串。当我将代码放入终端时,它说: (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 } } } 

但它返回一个向量/字符串列表。我希望所有这些情况都适用于同一个 string2 对象。因此,如果我在“hello”上测试该方法,它应该返回“OLLEH”。

谢谢

4

4 回答 4

1

你忘记了yield之后的a for ( ... ),因此最后一个for简单地运行,扔掉体内的所有东西,最后返回一个 unit ()

如果你想返回一些东西,你应该使用类似的东西:

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到到目前为止累积的所有转换的结果。

于 2018-02-05T19:43:26.253 回答
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 这样的函数式编程语言)。

于 2018-02-05T19:45:15.937 回答
0

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

stringPipeline: (string1: String)String => Unit

即一个函数,它接受一个字符串string1作为输入,并返回一个以第二个字符串 string2 作为输入的闭包,然后返回Unit,这就像void在 Java 中一样,只有 value ()

那么为什么返回的闭包有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的 instring1然后返回()。换句话说,for就是不让里面产生的价值通过。

如果要打印字符串“大写”,则需要编写

    case 'u' => println("Upper Case")

然后闭包的返回值仍然是(),但它的评估将打印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
        }
    )
}
于 2018-02-05T19:46:27.717 回答
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
于 2018-02-05T20:24:56.210 回答