Scala中简洁的方法来组合filterNot / match / case

时间:2016-02-19 03:14:59

标签: scala

我需要过滤一个序列以删除与某个案例匹配的元素。

这看起来太笨拙了:

val filtered = 
   headers.filterNot{ case Authorization(_) => true; case _ => false }

是否有更简洁/惯用的方式?

5 个答案:

答案 0 :(得分:3)

您可以使用isInstanceOf,就像这样

headers.filterNot(_.isInstanceOf[Authorization])

答案 1 :(得分:2)

您可以使用PartialFunction.cond来省略错误案例:

import PartialFunction.cond

headers.filterNot(cond(_) { case Authorization(_) => true } )

答案 2 :(得分:1)

你做事的方式似乎很好。或者,您可以利用case语句为PartialFunction的事实并利用它。不幸的是,Scala的挑剔型推断使得它比它应该更加冗长(否则它将是一个非常好的小成语)。

// Ideal, but Scala's type inference lets us down and this won't compile :(
val filtered0 = headers.filterNot({ case Authorization(_) =>}.isDefinedAt) 
// This will compile, but is crazily verbose
val filtered1 = headers.filterNot(({ case Authorization(_) =>}: PartialFunction[spray.http.HttpHeader, Option[Unit]]).isDefinedAt)

或者你可以将它全部包含在一个隐式类中,并在那里处理类型签名并保持调用站点原始。

implicit class Matches[T](x: T){
  def matches(pf: PartialFunction[T, Any]) = pf isDefinedAt x
}

val filtered2 = headers filterNot (_ matches {case Authorization(_) =>})
List(Some(1), None) filterNot (_ matches {case None =>}) // List(Some(1))

因为这只是利用case语句为PartialFunction的事实,这适用于任意模式。

List((5, 2, 'a'), (3, 4, 'b'), (3, 2, 'c')) filterNot (_ matches {case (3, _, x) if x == 'c' =>})
// List((5, 2, a), (3, 4, 'b'))

matches这个想法是对Adriaan Moors' idea on the Scala mailing list的一次小修饰,讨论是否将matches添加为自己的句法特征,其中OP会遇到您描述的确切问题。

答案 3 :(得分:0)

input class="dateinput form-control" data-date-autoclose="true" data-date-format="yyyy-mm-dd" data-date-start-date="0d" data-date-today-highlight="true" data-provide="datepicker" id="id_target_completion_date" name="target_completion_date" type="text">

你可以使用scala> sealed trait Header defined trait Header scala> case object Token extends Header defined object Token scala> case class Authorization(x: String) extends Header defined class Authorization scala> val headers: List[Header] = List(Token, Authorization("foo")) headers: List[Header] = List(Token, Authorization(foo)) ,即使它除了flatMap之外没有给你买任何东西。虽然我个人认为filterNotflatMap更容易理解 - 主要是由于我的习惯使用filterNot,但不是filter:< / p>

filterNot

答案 4 :(得分:0)

与原始提案类似,但在类型上进行模式匹配,

headers.filter { 
  case x: Authorization => false
  case _                => true 
}

另一种方法涉及过滤谓词的定义,

def noAuth(h: Header): Boolean = h match {
  case h: Authorization => false
  case _                => true
}

然后用于过滤,

headers.filter(noAuth)