学习Scala和我一直想要一个与LINQ的Single()方法等效的方法。示例,
val collection: Seq[SomeType]
val (desiredItem, theOthers) = collection.partition(MyFunc)
desiredItem.single.doSomething
// ^^^^^^
我可以使用desiredItem.head
,但如果MyFunc真的匹配了几个呢?我要保证只有一个。
编辑#2重复的问题说"不,没有,但下面是如何构建它"。所以我想,如果这是一个普遍的需要,它将是在基础API。正确编写的Scala程序需要这个吗?
我会使用更详细的东西,而不是single
:
(desiredItem match {
case Seq(single) => single
case _ => throw IllegalStateException("Not a single element!")
}).doSomething
它相对于single
的优势在于,它允许您在异常情况下显式控制行为(trow an exception,返回回退值)。
或者,您可以使用析构函数赋值:
val Seq(single) = desiredItem
single.doSomething
在这种情况下,如果desiredItem
不包含恰好一个元素,则会得到MatchError
。
UPD:我再次查看了您的代码。破坏任务是你的出路:
val collection: Seq[SomeType]
val (Seq(desiredItem), theOthers) = collection.partition(MyFunc)
desiredItem.doSomething
API中没有预构建的方法可以做到这一点。不过,您可以创建自己的方法来做类似的事情。
scala> def single[A](xs: List[A]) = xs match{
| case List() => None
| case x::Nil => Some(x)
| case x::xs => throw new Exception("More than one element")
| }
single: [A](xs: Seq[A])Option[A]
scala> single(List(1,2,3))
java.lang.Exception: More than one element
at .single(<console>:11)
... 33 elided
scala> single(List(1))
res13: Any = Some(1)
scala> single(List())
res14: Any = None
与其他说明一样,您所寻求的内容没有库实现。但是使用Pimp My Library方法很容易实现您自己的方法。例如,您可以执行以下操作。
object Main extends App {
object PML {
implicit class TraversableOps[T](val collection: TraversableOnce[T]) {
def single: Option[T] = collection.toList match {
case List(x) => Some(x)
case _ => None
}
}
}
import PML._
val collection: Seq[Int] = Seq(1, 2)
val (desiredItem, theOthers) = collection.partition(_ < 2)
println(desiredItem.single) // Some(1)
println(collection.single) // None
println(List.empty.single) // None
}