【问题标题】:Filtering a Scala List过滤 Scala 列表
【发布时间】:2021-02-09 10:35:04
【问题描述】:

我需要创建一个函数,该函数采用双精度并基于第一个返回新列表,其中包括属于 范围的第一个列表中元素的绝对值。我需要使用过滤。我有一个想法,但它不起作用。对不起,也许我的问题很简单,但我是个初学者:)

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

【问题讨论】:

  • 远离foreach()。它不会像你想的那样做。使用filter() 获取所需元素并使用map() 修改它们。
  • 您的示例不起作用,因为List 附加运算符不是+ 而是:+。顺便说一句,在 scala 中最好不要使用vars。所以它会起作用:newList = newList :+ scala.math.abs(element) 但看看答案,有更好的解决方案。

标签: scala scala-collections


【解决方案1】:

最佳实践解决方案

您可以通过以下方式轻松做到这一点

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

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

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

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

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


关于您提出的解决方案的说明

您的解决方案本身并没有错,但是实现已经是 filtermapcollect 等收集方法的一部分的逻辑很容易出错。如果您想修正您的方法,您只需将newList += ... 替换为newList :+= ...。这是因为将元素添加到不可变的 List 是使用 list :+ element 完成的(或者如果你想在前面添加 element +: list)。 list :+= elementlist = list :+ element 的语法糖。同样,这些不是您应该经常遇到的构造,因为除非您知道自己有充分的理由使用可变性,否则这种样式通常是不受欢迎的。

【讨论】:

    猜你喜欢
    • 2011-05-27
    • 1970-01-01
    • 2016-11-15
    • 2013-09-19
    • 2016-02-05
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 2015-11-28
    相关资源
    最近更新 更多