Ответ 1
Как насчет этого?
mySeq.headOption.map { _ =>
mySeq.map { elmt =>
// do stuff
}
}.getOrElse {
// some other stuff
}
Существует ли более короткий/лучший способ сделать следующее:
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)
Недавно я gisted помощник, который генерирует некоторый 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")
Это приведет к String
1, 2, 3
и приведет к String
Empty list
, если список пуст.