Как найти соответствующий элемент в списке и отобразить его как метод Scala API? - PullRequest
20 голосов
/ 30 марта 2011

Есть ли способ сделать следующее, не используя оба метода: find и map?

val l = 0 to 3
l.find(_ * 33 % 2 == 0).map(_ * 33) // returns Some(66)

Ответы [ 4 ]

28 голосов
/ 30 марта 2011

Как насчет использования сбора?

// Returns List(66)
List(1, 2, 3) collect { case i if (i * 33 % 2 == 0) => i * 33 }

Однако это вернет все совпадений, а не только первый.

Лучший ответ был бы на основена Scala 2.9:

// Returns Some(66)
List(1, 2, 3) collectFirst { case i if (i * 33 % 2 == 0) => i * 33 }

Решение, предложенное в комментариях, добавить head, чтобы получить версию Scala 2.8, что, боюсь, не очень эффективно.Возможно, в этом случае я бы придерживался вашего собственного кода.В любом случае, чтобы убедиться, что он возвращает опцию, вам не следует звонить head, но headOption.

// Returns Some(66)
List(1, 2, 3) collect { case i if (i * 33 % 2 == 0) => i * 33 } headOption
19 голосов
/ 25 ноября 2014

Если вы не хотите выполнять операцию map() несколько раз (например, если это дорогой поиск в БД), вы можете сделать это:

l.view.map(_ * 33).find(_ % 2 == 0)

The view делает коллекцию ленивой, поэтому количество операций map() сводится к минимуму.

6 голосов
/ 30 марта 2011

Эй, смотри, это мой маленький приятель findMap снова!

/**
 * Finds the first element in the list that satisfies the partial function, then 
 * maps it through the function.
 */
def findMap[A,B](in: Traversable[A])(f: PartialFunction[A,B]): Option[B] = {
  in.find(f.isDefinedAt(_)).map(f(_))
}

Обратите внимание, что, в отличие от принятого ответа, но, как и метод collectFirst, упомянутый в одном из его комментариев, этот парень останавливается, как только находит соответствующий элемент.

0 голосов
/ 30 марта 2011

Это может сделать это, но было бы легче, если бы вы сказали, чего вы на самом деле пытаетесь достичь:

l.flatMap(n => if (n * 33 % 2 == 0) Some(n * 33) else None).headOption
...