2012-01-20 4 views
6

지도와 널 건너 뛰기가 한 번의 호출로 표현되는 방식으로 다음 코드를 표현할 수 있습니까? 당신이스칼라에서 맵과 필터가 null 인 경우

for { 
    item <- list 
    itemConverted = item.accept(this, arg).asInstanceOf[T] 
    itemNonNull = itemConverted if itemConverted != 0 
} yield itemNonNull 

이 가능할 것이다 collect을 사용하여 (이것은 원래의 표현에 더 많거나 적은 변환됩니다 불구하고), 좋아하지만 경우

list.map(_.accept(this, arg).asInstanceOf[T]).filter(_ != null) 
+0

을'그 _.accept (이, ARG) ''null '을 반환 할 수 있습니다. 이 경우에는 약간 더 관용적이다. (여전히 두 번 호출이있다.)'list.map (i => Option (i.accept (this, arg) .asInstanceOf [T])). flatten' –

+1

' 잘못되었지만'map'과'filter'의 조합을'collect'하지 않았습니까? 아니면 다른 방법 이었습니까? 또는 나는 틀린가? ;) – agilesteel

+1

@agilesteel, 예, collect가 작동 할 수 있습니다. 코드 스 니펫을 제공 할 수 있습니까? –

답변

11
list flatMap { i => Option(i.accept(this, arg).asInstanceOf[T]) } 

또는 대안, 그것은 가능성이 두 배 accept를 부를 것이다 대부분의 주장에서 부분 함수에 대한 시험 때문에 :

list collect { 
    case i if i.accept(this, arg).asInstanceOf[T] != null => i.accept(this, arg).asInstanceOf[T] 
} 

이것을 방지하려면 메모 작성기 (또는 스마트 추출기)를 사용해야합니다.

+0

답해 주셔서 감사합니다! –

6

성능에 대해 우려하고 있다면, 당신은 따라서 mapfilter 목록이 아닌 두 개의 패스를 통해 한 번에 수행됩니다, .view

list.view.map(_.accept(this, arg).asInstanceOf[T]).filter(_ != null) 

view이 통과가 지연 될됩니다 추가 할 수 있습니다. 이 패턴을 재사용이 걱정되는 경우

, 당신은 당신의 자신의 도우미 함수 정의 할 수 있습니다 같아요

def mapNN[A,B](list: List[A])(f: A => B) = { 
    list.view.map(f(_)).filter(_ != null) 
} 

mapNN(list)(_.accept(this, arg).asInstanceOf[T]) 

테스트 ...

> mapNN(List(1,2,3))(x => if (x%2==0) x else null).toList 
res7: List[Any] = List(2) 
+0

이 부분에 대해 더 설명해 주시겠습니까? 맵과 필터는 두 번의 개별적인 패스가 아닌 한 번의 패스로 수행됩니다 ._? 어떻게 2 개의 변환을 적용하기 위해 하나의 패스 만 필요합니까? –

+1

@MinhThai 다음은'view'에 대한 적절한 설명입니다 : https://stackoverflow.com/a/6799739/208257 기본적으로 변환은 게으르다. 'toList'를 호출 할 때까지 단일 패스를 수행하는 것을 지연합니다.이 시점에서 단일 패스를 수행하고 각 변환을 점진적으로 적용합니다. –

관련 문제