Условно отфильтровать последовательность - PullRequest
5 голосов
/ 07 февраля 2012

Предположим, у меня есть Option[A => Boolean], List[A] и некоторый набор операций, которые я хочу выполнить над подмножеством этого списка.Если опция установлена, тогда я хочу сначала отфильтровать список, а затем применить свои операции.Если нет, то я хочу применить его ко всему списку.Пример:

val a : Option[Int => Boolean] = Option((a : Int) => a % 2 == 0)
val b = 1 to 100

Я легко могу сделать следующее:

val c = if (a.isDefined) b.filter(a.get) else b

Однако это включает вызов a.get;большая обусловленность оставляет меня неспособным сделать это!В качестве альтернативы я мог бы сделать:

val c = b.filter(a.getOrElse(_ => true))

Это кажется лучше, но теперь я застрял со второй (хотя и тривиальной) операцией, выполняемой для каждого элемента моей последовательности.Я мог бы надеяться, что это будет оптимизировано, но это все еще кажется несовершенным.

То, что я хотел бы, - то, что испытывает недостаток или недостаток.Такое ощущение, что должен быть хороший способ сделать это - есть идеи?

Ответы [ 4 ]

10 голосов
/ 07 февраля 2012

Вам просто нужно использовать обычные методы обработки опций:

a.map(b.filter).getOrElse(b)
3 голосов
/ 07 февраля 2012

По сути то же самое, что и решение Rex Kerr, но использует fold от Scalaz, чтобы сделать его немного более кратким.

В общем, x.fold(f, g)x.map(f).getOrElse(g).

scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._

scala> a.fold(b.filter, b)
res112: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100)
1 голос
/ 07 февраля 2012

Я лично предпочитаю четкость сопоставления с образцом;это очень прямой перевод из вашего прозаического описания в код:

val c = a match {
  case Some(f) => b.filter(f)
  case None => b
}
1 голос
/ 07 февраля 2012

Как насчет замены на:

val a : Option[Seq[Int] => Seq[Int]] = Option((a : Seq[Int]) => a.filter(_ % 2 == 0))
val b = 1 to 100
val c = a.getOrElse((f:Seq[Int]) => f)(b)

(Обратите внимание, я не пробовал выше, но это должно дать вам идею)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...