简体   繁体   English

SCALA:有条件的折叠方法

[英]SCALA: Fold method with conditions

I am still learning the basics of Scala, therefore I am asking for your understanding.我仍在学习 Scala 的基础知识,因此我请求您的理解。 Is it any possible way to use fold method to print only names beginning with "A"是否有任何可能的方法使用折叠方法仅打印以“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: ")(_+_));  
    }
  }
}

Have a look at the signature of foldLeft看一下foldLeft的签名

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

where在哪里

  • z is the initial value z是初始值
  • op is a function taking two arguments, namely accumulated result so far B , and the next element to be processed A op是一个 function 取两个 arguments ,即到目前为止的累加结果B ,下一个要处理的元素A
  • returns the accumulated result B返回累加结果B

Now consider this concrete implementation现在考虑这个具体的实现

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
}

here这里

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

Usually we would write this inlined and rely on type inference so we do not have two write out full types all the time, so it becomes通常我们会写这个内联并依赖类型推断,所以我们不会一直有两个写出完整类型,所以它变成

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

On of the key ideas when working with List is to always prepend an element instead of append使用List时的一个关键想法是始终预先添加一个元素而不是 append

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

because prepending is much more efficient.因为前置效率更高。 However note how this makes the accumulated result in reverse order, so但是请注意这如何使累积的结果以相反的顺序排列,所以

List(Ann, Adam)

instead of perhaps required而不是可能需要

List(Adam, Ann)

so often-times we perform one last traversal by calling reverse like so所以很多时候我们通过调用reverse来执行最后一次遍历

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

The answer from @Mario Galic is a good one and should be accepted. @Mario Galic 的回答很好,应该被接受。 (It's the polite thing to do). (这是礼貌的做法)。

Here's a slightly different way to filter for starts-with-A strings.这是过滤以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"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM