如何从scala中的列表中按类型查找项?

如何从scala中的列表中按类型查找项?,scala,Scala,假设我定义了: sealed trait ValidationResult object Valid extends ValidationResult case class Invalid(error:String) extends ValidationResult 然后我有一个列表,其中包含一些验证结果: val results = List(Valid, Invalid("required username"), Valid) 我想找到第一个类型为无效的: results.find( ?

假设我定义了:

sealed trait ValidationResult
object Valid extends ValidationResult
case class Invalid(error:String) extends ValidationResult
然后我有一个列表,其中包含一些验证结果:

val results = List(Valid, Invalid("required username"), Valid)
我想找到第一个类型为
无效的

results.find( ??? ) match {
    case Some(error) => println("Invalid: " + error)
    case _ => println("No error")
}
您可以看到在
查找
中有一个
,但我不知道应该在那里输入什么

results.find {
  case Invalid(_) => true
  case _ => false
} match {
  case Some(Invalid(error)) => println("Invalid: " + error)
  case _ => println("No error")
}
或者可能:

results.collectFirst {
  case Invalid(error) => error
} match {
  case Some(error) => println("Invalid: " + error)
  case _ => println("No error")
}
现在不需要,但我会将Valid转换为case对象,以防您希望模式匹配它


注意:两个版本都返回找到的第一个错误。如果要累积错误,则需要过滤和映射(或折叠)。

使用列表
span

val (v,inv) = results.span { _ match { 
    case Invalid(_) => false  
    case _ => true 
  } 
}
返回

(v, inv) = (List(Valid),
            List(Invalid(required username), Valid))
在结果对中

  • 第一个元素是从列表开始出现的所有有效结果的列表
  • 第二个元素是以不包含谓词的第一项开始的列表
因此,我们可以使用

if (inv.isEmpty) 
  Valid 
else 
  inv.head

res: Invalid(required username)