2016-10-02 4 views
1

의 컬렉션의 첫 번째 정의 항목, f 전체 수집을 평가하지 않고 정의 된 coll의 첫 번째 항목을 얻을 스칼라의 관용적 방법은 무엇 찾기?모음, <code>coll: C[A]</code> 및 기능 <code>f: A => Option[B]</code>을 감안할 때 스칼라

def findFirstDefined[A, B](coll: Traversable[A])(f: A => Option[B]): Option[B] 

coll.flatMap(f).headOption 같은 본래의 접근법은 전체 모음을 평가하는 것입니다 :

여기에 내 의도 한 서명입니다. 우리는 아마도 coll.view.flatMap(f).headOption이나 coll.collectFirst(Function.unlift(f))을 할 수 있지만, 표준 라이브러리 나 기능 프로그래밍 관련 문헌 또는 scalaz/cats에 뭔가 다른 것이 있습니다.

+0

다음 IsDefined)'꽤 기능적인 해결책이 있는지 확실하지 않습니다. –

+2

'coll.view.flatMap (f) .headOption'은 컴파일되지 않습니다 (모나드는 결합하지 않습니다). 그러나'coll.collectFirst (Function.unlift (f))'의 문제점은 무엇입니까? 나에게 좋은 해결책 인 것 같아. –

+1

@ Łukasz 발견 된 요소에 대해'f'를 두 번 호출해야합니다. '.collectFirst (Function.unlift (f))'는이 측면에서 더 좋습니다. –

답변

0

이 괜찮은 솔루션처럼 보인다. 난 그냥`coll.find (F (_)을 할 것

def findFirstDefined[A, B](coll: Traversable[A])(f: A => Option[B]): Option[B] = 
    coll.collectFirst(Function.unlift(f)) 
0

find(p: A => Boolean)을 사용하면 어떨까요?

def findFirstDefined[A, B](coll: Traversable[A])(f: A => Option[B]): Option[B] = 
    coll.find(f(_).isDefined).flatMap(f(_)) 

이것은 f.apply()를 두 번 호출을 필요로하지만 정의 된 옵션을 반환하는 첫 번째 요소가 발견 될 때까지 apply()를 호출합니다.

편집 : 당신이 뭔가 표준을 사용하려는 경우

coll.collectFirst(Function.unlift(f)) 
2

이 IMO coll.collectFirst(Function.unlift(f))이 좋은 해결책처럼 보인다 : 그것에 대해 생각 (그러나 빅터는 하나에 나를 이길은), collectFirst()뿐만 아니라 더 우아한 옵션입니다. 그러나 사용하여 재귀를 구현하기 매우 쉽습니다 :

질문에서 언급 한 바와 같이
@annotation.tailrec 
def findFirstDefined[A, B](coll: Traversable[A])(f: A => Option[B]): Option[B] = 
    if (coll.isEmpty) None 
    else { 
    val r = f(coll.head) 
    if (r.isEmpty) findFirstDefined(coll.tail)(f) 
    else r 
    } 
+0

'collectFirst'는'applyOrElse'를 사용하기 때문에 두 번 평가하지 않습니다. 'Function.unlift'에 대한 scaladoc은 잘못된 인상을줍니다. –

+0

@ som-snytt 루카스의 제안에서'f'가 두 번 평가되고 collectFirst ...가'applyOrElse' 때문에 더 좋은 방법이라고 언급했습니다. –

+0

예, 다시 그 부분을 알아 내야 했으므로 다음 사람을 위해 언급했습니다. –