过滤 Scala 列表

Filtering a Scala List

我需要基于第一个创建包含双精度和 returns 新列表的函数,该列表包含第一个列表中属于 <-5,12> 范围的元素的绝对值.我需要使用过滤。我有一个想法,但行不通。对不起,也许我的问题很简单,但我是初学者:)

var numbersReal = List(2.25, -1, -3, 7.32, 0.25, -6, 0, 2, 0, 1, 0, 2.99, 3.02, 0)
 
 def magicFilter(list: List[Double]): List[Double] = {
    var newList = List[Double]()
    list.foreach {element => if (-5 <= element && element <= 12) newList += scala.math.abs(element) }
    newList.toList
 }
println(magicFilter(numbersReal))

最佳实践解决方案

您可以结合使用

轻松做到这一点
  • filter:只保留满足给定谓词/条件的元素。对于我们来说,它将只保留 [-5,12]
  • 中的元素
  • map:对每个元素应用一个函数。对于我们来说,它将取绝对值。
numbersReal.filter(e => e >= -5 && e <= 12).map(math.abs)

在“one-shot”中实现此目的的另一种方法是使用 collect,它结合了 filtermap:

numbersReal.collect { case e if e >= 5 && e <= 12 => math.abs(e) }

我个人认为第一个解决方案在这种特殊情况下更具可读性,但这是一个见仁见智的问题。

通常,这些问题无需借助 var 或任何可变集合即可解决。 Scala 的集合是它最伟大的资产之一,因为它们包含了很多这些原始操作,并且大多数问题都可以通过组合它们来解决。


关于您提出的解决方案的注意事项

您的解决方案没有错 per-se,但是实现已经属于收集方法一部分的逻辑非常 error-prone,例如 filtermapcollect。如果您想修复您的方法,只需将 newList += ... 替换为 newList :+= ...。这是因为将元素添加到不可变的 List 是通过 list :+ element 完成的(或者 element +: list 如果你想添加)。 list :+= elementlist = list :+ element 的语法糖。同样,这些不是你应该经常遇到的结构,因为这种风格通常是 frowned-upon 除非你知道你有充分的理由使用可变性。