是否有更短/更好的方法来执行以下操作:
mySeq.map { elmt =>
// do stuff
}
if (mySeq.isEmpty) {
// some other stuff
}
Ps:我正在使用 PlayFramework,这意味着在模板中使用,所以如果我错过了任何“帮助者”,我会很高兴发现那些 ;)
是否有更短/更好的方法来执行以下操作:
mySeq.map { elmt =>
// do stuff
}
if (mySeq.isEmpty) {
// some other stuff
}
Ps:我正在使用 PlayFramework,这意味着在模板中使用,所以如果我错过了任何“帮助者”,我会很高兴发现那些 ;)
这个怎么样?
mySeq.headOption.map { _ =>
mySeq.map { elmt =>
// do stuff
}
}.getOrElse {
// some other stuff
}
您可以使用match
:
l match {
case l if !l.isEmpty => l.map{ // do stuff }
case _ => // some other stuff
}
对于List
:
l match {
case h :: t => l.map{ // do stuff }
case _ => // some other stuff
}
或者,您可以定义自己的方法:
import scala.collection.generic.CanBuildFrom
import scala.collection.TraversableLike
class FoldEmpty[T, S[T] <: TraversableLike[T, S[T]]](l: S[T]){
def foldEmpty[B, That](notEmpty: T => B, empty: => That)(implicit cbf: CanBuildFrom[S[T], B, That]): That =
l match {
case t if !t.isEmpty => l map notEmpty
case _ => empty
}
}
implicit def seqToFoldEmpty[T, S[T] <: TraversableLike[T, S[T]]](l: S[T]) = new FoldEmpty(l)
用法:
scala> IndexedSeq(1, 2, 3).foldEmpty( _ + 1 , IndexedSeq(-1))
res0: IndexedSeq[Int] = Vector(2, 3, 4)
scala> IndexedSeq[Int]().foldEmpty( _ + 1 , Seq(-1))
res1: Seq[Int] = List(-1)
我最近提供了一个助手,它仅在给定序列非空时生成一些 HTML。把这个微小的变化放在一个文件中,例如Helpers.scala
:
package views.html.helper
import play.api.templates.Html
object nonEmptyOrElse {
def apply[T <: Seq[_]](t: T)(nonEmptyBlock: (T) => Html)(emptyBlock: => Html) = {
if (t.nonEmpty) nonEmptyBlock(t) else emptyBlock
}
}
并在您的模板中像这样使用它:
@nonEmptyOrElse(mySeq) { seq =>
//doSomething with entire seq
} {
// do something else
}
编辑:这是映射每个元素的版本:
object mapOrElse {
def apply[T](t: Seq[T])(nonEmptyBlock: (T) => Html)(emptyBlock: => Html) = {
if (t.nonEmpty) t.map(nonEmptyBlock(_)) else emptyBlock
}
}
在范围内具有以下简单扩展:
(对于 Scala 2.10):
implicit class AnyExtensions[A] ( val x : A ) extends AnyVal {
def asSatisfying(p: A => Boolean): Option[A] =
if (p(x)) Some(x) else None
}
(对于 Scala 2.9):
implicit def anyExtensions[A] (x : A) = new {
def asSatisfying(p: A => Boolean): Option[A] =
if (p(x)) Some(x) else None
}
您将能够按如下方式重写您的代码:
mySeq
.asSatisfying{_.nonEmpty}
.map{
_.map{elmt =>
// do stuff
}
}
.getOrElse{
// some other stuff
}
在我的实践中,这个扩展在很多情况下都适用并且非常有用。它在您意识到需要if
在表达式中间使用语句的情况下表现出色,如果没有此扩展,则需要您引入临时变量。这是一个例子:
List(1, 2, 3).mkString(", ").asSatisfying{_.nonEmpty}.getOrElse("Empty list")
如果列表为空,它将导致 aString
1, 2, 3
并且会导致 a 。String
Empty list
这是一个有用的值类,如果 Seq.isEmpty,则将 Seq[A] 转换为 None,否则将其包装在 Some[Seq[A]] 中。
对于 Scala 2.10:
/**
* A value type class to add some useful utility methods to Seq
*
* @param underlying The Seq to augment.
*/
implicit class SeqExt[+A](private val underlying: Seq[A]) extends AnyVal {
/** If this Seq is empty, returns None, otherwise builds a new collection by
* applying a function to all elements of this immutable sequence, and wraps
* the Seq in an Option.
*
* @tparam B The element type of the returned collection.
* @param f The function to apply to each element.
* @return If this Seq is empty, returns None, otherwise builds a new collection by
* applying a function to all elements of this immutable sequence, and wraps
* the Seq in an Option.
*/
def mapOption[B](f: (A) ⇒ B): Option[Seq[B]] = {
if(underlying.isEmpty) None else Some(underlying.map(f))
}
}
用法(如您的示例):
mySeq
.mapOption { elmt =>
// do stuff to each element if mySeq.nonEmpty
}
.getOrElse {
// some other stuff if mySeq.isEmpty
}