필터 대신 withFilter
나중에 map, flatmap 등과 같은 기능을 적용 할 때 필터 대신 withFilter를 사용하는 것이 항상 더 성능이 좋은가요?
map, flatmap 및 foreach 만 지원되는 이유는 무엇입니까? (forall / exists와 같은 예상 기능)
에서 스칼라 문서 :
참고 사이의 차이
c filter p
와c withFilter p
후자는 단지 다음의 영역으로 제한하는 반면, 전자는, 새로운 집합을 생성하는이고map
,flatMap
,foreach
, 및withFilter
작업.
따라서 filter
원래 컬렉션을 가져와 새 컬렉션을 생성하지만 withFilter
필터링되지 않은 값을 나중에 map
/ flatMap
/ withFilter
호출에 엄격하게 (즉, 느리게) 전달 하여 (필터링 된) 컬렉션을 통한 두 번째 패스를 절약합니다. 따라서 이러한 후속 메서드 호출을 전달할 때 더 효율적입니다.
사실, withFilter
는 이러한 방법의 체인으로 작업하도록 특별히 설계되었으며, 이것이 바로 이해를위한 것입니다. 이를 위해 다른 메서드 (예 : forall
/ exists
)가 필요하지 않으므로 FilterMonadic
반환 유형에 추가되지 않았습니다 withFilter
.
의 또한 어둠의 땅의 우수한 대답 , 나는 사이의 차이의 직관적 인 예를 가지고 싶습니다 filter
와 withFilter
.
다음 코드를 살펴 보겠습니다.
val list = List(1, 2, 3)
var go = true
val result = for(i <- list; if(go)) yield {
go = false
i
}
대부분의 사람들 result
은 List(1)
. 이것은 Scala 2.8 이후의 경우입니다.
val result = list withFilter {
case i => go
} map {
case i => {
go = false
i
}
}
보시다시피 번역은 조건을 withFilter
. 이전 Scala 2.8, for-comprehension은 다음과 같이 번역되었습니다.
val r2 = list filter {
case i => go
} map {
case i => {
go = false
i
}
}
를 사용 filter
하면의 값 result
이 상당히 다릅니다 List(1, 2, 3)
.. 우리가 go
플래그 false
를 만들고 있다는 사실 은 필터가 이미 완료 되었기 때문에 필터에 영향을 미치지 않습니다. 다시 말하지만 Scala 2.8에서이 문제는 withFilter
. 경우 withFilter
사용되며, 상태는 소자가 내부에 액세스 할 때마다 평가 map
방법.
참조 :-p.120, Scala in action (Scala 2.10 포함), Manning Publications, Milanjan Raychaudhuri- 이해를위한 번역에 대한 Odersky의 생각
forall / exists 가 구현되지 않은 주된 이유 는 사용 사례가 다음과 같기 때문 입니다.
- 무한 스트림 / 반복 가능에 withFilter를 느리게 적용 할 수 있습니다.
- 다른 withFilter를 느리게 적용 할 수 있습니다.
forall / exist 를 구현하려면 게으름을 없애고 모든 요소를 얻어야합니다.
예를 들면 다음과 같습니다.
import scala.collection.AbstractIterator
class RandomIntIterator extends AbstractIterator[Int] {
val rand = new java.util.Random
def next: Int = rand.nextInt()
def hasNext: Boolean = true
}
//rand_integers is an infinite random integers iterator
val rand_integers = new RandomIntIterator
val rand_naturals =
rand_integers.withFilter(_ > 0)
val rand_even_naturals =
rand_naturals.withFilter(_ % 2 == 0)
println(rand_even_naturals.map(identity).take(10).toList)
//calling a second time we get
//another ten-tuple of random even naturals
println(rand_even_naturals.map(identity).take(10).toList)
참고 ten_rand_even_naturals는 여전히 반복자입니다. toList 를 호출 할 때만 난수가 생성되고 체인으로 필터링됩니다.
Note that map(identity) is equivalent to map(i=>i) and it is used here in order to convert a withFilter object back to the original type (eg a collection , a stream, an iterator)
For the forall/exists part:
someList.filter(conditionA).forall(conditionB)
would be the same as (though a little bit un-intuitive)
!someList.exists(conditionA && !conditionB)
Similarly, .filter().exists() can be combined into one exists() check?
Using for yield can be a work around, for example:
for {
e <- col;
if e isNotEmpty
} yield e.get(0)
As a workaround, you can implement other functions with only map
and flatMap
.
Moreover, this optimisation is useless on small collections…
참고URL : https://stackoverflow.com/questions/19617378/withfilter-instead-of-filter
'IT TIP' 카테고리의 다른 글
Python, 가변 길이 위치 인수 뒤의 기본 키워드 인수 (0) | 2020.10.14 |
---|---|
Thread.sleep 대 TimeUnit.SECONDS.sleep (0) | 2020.10.14 |
np.mean과 tf.reduce_mean의 차이점은 무엇입니까? (0) | 2020.10.14 |
VueJS의 Angular Service에 해당하는 것은 무엇입니까? (0) | 2020.10.14 |
bindActionCreators는 언제 react / redux에서 사용됩니까? (0) | 2020.10.14 |