如何在Scala列表中找到元素的最后出现?

obl*_*ion 5 scala

我有一个Student列表,我想从中找到最后一个匹配的年龄为23岁的学生。

我知道该find()方法为我们提供了第一个匹配项,如下所示:

case class Student(id: Int, age: Int)

val students = List(Student(1, 23), Student(2, 24), Student(3, 23))

val firstStudentWithAge23 = students.find(student => student.age == 23)
// Some(Student(1, 23))
Run Code Online (Sandbox Code Playgroud)

这段代码给了我第一个匹配的学生。但是我需要最后一个匹配的学生。

现在,我使用的reverse方法是find

val lastStudentWithAge23 = students.reverse.find(student => student.age == 23)
// Some(Student(3,23))
Run Code Online (Sandbox Code Playgroud)

这给了我最后一个匹配的学生。

但这似乎不是一个好方法,因为必须首先将整个列表颠倒。我怎样才能以更好的功能实现这一目标?

Nth*_*tal 7

从Scala 2.13开始,您可以使用findLast来找到Seq满足条件的谓词的最后一个元素(如果存在):

val students = List(Student(1, 23), Student(2, 24), Student(3, 23))
students.findLast(_.age == 23) // Option[Student] = Some(Student(3, 23))
Run Code Online (Sandbox Code Playgroud)


che*_*ohi 5

我想也许你可以通过filterwith来实现这一点lastOption,比如:

list.filter(student => student.age == 23).lastOption
Run Code Online (Sandbox Code Playgroud)


Luk*_*itz 5

chengpohi's 和jwvh's 答案有效,但会遍历列表两次或更多次。

这是查找仅遍历列表一次的最后一次出现的通用方法:

def findLast[A](la: List[A])(f: A => Boolean): Option[A] =
  la.foldLeft(Option.empty[A]) { (acc, cur) => 
    if (f(cur)) Some(cur)
    else acc
  }
Run Code Online (Sandbox Code Playgroud)

我们只遍历集合一次,并且总是取与我们的谓词匹配的最后一个元素f