0

我仍在学习 Scala 的基础知识,因此我请求您的理解。是否有任何可能的方法使用折叠方法仅打印以“A”开头的名称

Object Scala {
  val names: List[String] = List("Adam", "Mick", "Ann");
  def main(args: Array[String]) {
  println(names.foldLeft("my list of items starting with A: ")(_+_));  
    }
  }
}
4

2 回答 2

3

看一下签名foldLeft

def foldLeft[B](z: B)(op: (B, A) => B): B

在哪里

  • z是初始值
  • op是一个接受两个参数的函数,即到目前为止的累积结果B和要处理的下一个元素A
  • 返回累计结果B

现在考虑这个具体的实现

val names: List[String] = List("Adam", "Mick", "Ann")
val predicate: String => Boolean = str => str.startsWith("A")

names.foldLeft(List.empty[String]) { (accumulated: List[String], next: String) =>
  if (predicate(next)) accumulated.prepended(next) else accumulated
}

这里

z = List.empty[String]
op = (accumulated: List[String], next: String) => if (predicate(next)) accumulated.prepended(next) else accumulated

通常我们会写这个内联并依赖类型推断,所以我们不会一直有两个写出完整类型,所以它变成

names.foldLeft(List.empty[String]) { (acc, next) =>
  if (next.startsWith("A")) next :: acc else acc
}
// val res1: List[String] = List(Ann, Adam)

使用时的关键思想List是始终预先添加元素而不是附加

names.foldLeft(List.empty[String]) { (accumulated: List[String], next: String) =>
  if (predicate(next)) accumulated.appended(next) else accumulated
}

因为前置效率更高。但是请注意这如何使累积的结果以相反的顺序排列,所以

List(Ann, Adam)

而不是可能需要

List(Adam, Ann)

很多时候我们通过reverse这样调用来执行最后一次遍历

names.foldLeft(List.empty[String]) { (acc, next) =>
  if (next.startsWith("A")) next :: acc else acc
}.reverse
// val res1: List[String] = List(Adam, Ann)
于 2020-06-07T15:24:27.787 回答
2

@Mario Galic 的回答很好,应该被接受。(这是礼貌的做法)。

这是过滤以A 开头的字符串的一种稍微不同的方法。

val names: List[String] = List("Adam", "Mick", "Ann")

println(names.foldLeft("my list of items starting with A: "){
  case (acc, s"A$nme") => acc + s"A$nme "
  case (acc, _ ) => acc
})

//output: "my list of items starting with A: Adam Ann"
于 2020-06-07T19:09:42.093 回答