在scala中过滤字符串列表的函数

Posted

技术标签:

【中文标题】在scala中过滤字符串列表的函数【英文标题】:Function to filter a list of strings in scala 【发布时间】:2021-12-25 07:17:15 【问题描述】:

我只是开始使用 Scala 编程或函数式编程。我应该编写一个过滤字符串列表的函数(练习中给出了 main 的第一行)。它应该返回单词“Hello people”。我已经使用变量来管理它,但我的老师告诉我修改它以不使用任何 var。我一直在尝试这样做,但我不知道为什么下面的代码不断返回错误。我会很感激任何帮助,因为我很难过。

main.scala:13: error: type mismatch;
 found   : Unit
 required: List[String]
      if(filter(workList.head))
      ^
1 error
exit status 1
object Main 
  
  def main(args: Array[String]): Unit = 
  println(filterList(List("Hello", "there", "people"), _.contains('l')).mkString(" "))


  def filterList(listToSort:List[String], filter: (String) => Boolean): List[String] = 
  
    @scala.annotation.tailrec
    def recFilter(workList: List[String], filteredList: List[String]): List[String] = 
      if(workList.isEmpty)
        return filteredList
      if(filter(workList.head))
        recFilter(workList.tail, workList.head :: filteredList)
    

    return recFilter(listToSort, List())
  
  

【问题讨论】:

1 - 不要使用return。这是不好的形式,会让你误入歧途。 2 - 每个if 都应该有一个else。事实上,如果您不提供else,那么编译器将为您提供一个。这就是您的错误的来源。带有默认 elseif 是一个计算结果为 Unit 的表达式。 使用模式匹配而不是调用ifEmpty / had & tail @jwvh 谢谢,缺少else 语句确实是个问题。 【参考方案1】:

我不确定练习的具体参数是什么,但是 scala 中的标准集合库可以为您做很多事情......

在这种情况下,List其实已经有了一个过滤方法……

List("Hello", "there", "people").filter(_.contains("l"))

可能值得浏览一下此类列表中的制表符补全并阅读有关建议的文档。

如果练习是编写自己的练习,那么显然,这不是有史以来最有帮助的答案,对此深表歉意。另一个想法可能是这样的;

def filterList(aList: List[String]) = 
  for (
    word <- aList
    if word.contains("l")
  ) yield 
    word
  


val filtered = filterList(testList)

这是 yield 语法的介绍...

【讨论】:

是的,我们必须编写自己的过滤函数。我以前有yield,我什至没有想过在那个例子中使用它。感谢您帮助我从另一个角度看待这个问题 酷 - 希望你对 Scala 玩得开心……我个人的偏好是可读性高于其他问题。一个想法可能是提出一系列解决方案并在几个月后回顾。我个人首选的解决方案是最容易理解的,你对任务的记忆已经消失……【参考方案2】:

这是一种使用带有辅助函数和模式匹配的递归的方法。

def filterList(xs: List[String], filter: String => Boolean): List[String] = 
  @scala.annotation.tailrec
  def filterListR(xs: List[String], filter: String => Boolean, acc: List[String]): List[String] = xs match
    case Nil                         => acc
    case head::tail if(filter(head)) => filterListR(tail, filter, head :: acc)
    case head::tail                  => filterListR(tail, filter, acc)
  
  filterListR(xs, filter, List[String]()).reverse

输出:

scala> filterList(List("Hello", "there", "people"), (s: String) => s.contains("l"))
val res3: List[String] = List(Hello, people)

【讨论】:

以上是关于在scala中过滤字符串列表的函数的主要内容,如果未能解决你的问题,请参考以下文章

spark-streaming scala:如何将字符串数组传递给过滤器?

scala中常用特殊符号

在每个谓词 scala 处将字符串列表拆分为多个列表

Scala链表***

Scala:基础知识01

Scala groupBy 项目列表中的所有元素