Подтвердить что ты не робот

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

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

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

Ответ 1

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

// 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

Ответ 2

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

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

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

Ответ 3

Эй, смотри, это мой маленький приятель 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, упомянутый в одном из своих комментариев, этот парень останавливается, как только находит соответствующий элемент.

Ответ 4

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

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