Daha sonra map, flatmap vb. İşlevleri uygularken filtre yerine Filtre ile kullanmak her zaman daha performanslı mıdır?
Neden sadece harita, daire haritası ve foreach destekleniyor? (Forall / gibi beklenen işlevler de var)
Daha sonra map, flatmap vb. İşlevleri uygularken filtre yerine Filtre ile kullanmak her zaman daha performanslı mıdır?
Neden sadece harita, daire haritası ve foreach destekleniyor? (Forall / gibi beklenen işlevler de var)
Yanıtlar:
Gönderen Scala docs :
Not: arasındaki fark
c filter p
vec withFilter p
ikincisi sadece müteakip etki alanını kısıtladığı oysa eski yeni koleksiyon oluşturur olmasıdırmap
,flatMap
,foreach
, vewithFilter
operasyonlar.
Böylece filter
, orijinal koleksiyonu alacak ve yeni bir koleksiyon üretecek, ancak (filtrelenmiş) koleksiyondan ikinci bir geçişi koruyarak, withFilter
filtrelenmemiş değerleri kesinlikle (yani tembel olarak) daha sonraki map
/ flatMap
/ withFilter
çağrılara geçirecektir. Bu nedenle, bu sonraki yöntem çağrılarına geçerken daha verimli olacaktır.
Aslında, withFilter
bu yöntemlerin zincirleriyle çalışmak için özel olarak tasarlanmıştır, bu anlayış için şekeri çözülür. Bunun için başka yöntem ( forall
/ gibi exists
) gerekmez, bu nedenle FilterMonadic
dönüş türüne eklenmemişlerdir withFilter
.
view
Haritaların / filtrelerin tembel olmasını istiyorsanız kullanın .
view
ve withFilter
? Görünüm neden kullanılmıyor for-loops
?
Don’t create temporary collections
bağlantılı bölümde arama yapabilirsiniz .
withFilter
, Martin Odersky, bunu şiddetle tavsiye ettiğim Coursera'daki Scala kurslarında açıkça kullanıyor. Bunu yaptığı düşünüldüğünde, diğerlerine de bunu yaparken rahatlık verebilir, ancak aradaki fark tipik olarak sadece 1 karakterdir. Örnek için seq.view filter p
vs. seq withFilter p
.
Shadowlands'in mükemmel cevabına ek olarak ,filter
ve arasındaki farkın sezgisel bir örneğini getirmek istiyorum withFilter
.
Aşağıdaki kodu düşünelim
val list = List(1, 2, 3)
var go = true
val result = for(i <- list; if(go)) yield {
go = false
i
}
Çoğu insan result
eşit olmayı bekler List(1)
. Scala 2.8'den beri durum böyledir, çünkü anlama
val result = list withFilter {
case i => go
} map {
case i => {
go = false
i
}
}
Gördüğünüz gibi çeviri koşulu bir çağrıya dönüştürüyor withFilter
. Scala 2.8'den önce, anlama için aşağıdaki gibi bir şeye çevrildi:
val r2 = list filter {
case i => go
} map {
case i => {
go = false
i
}
}
Kullanılması filter
, değeri result
oldukça farklı olacaktır: List(1, 2, 3)
. go
Bayrak oluşturmamızın false
filtre üzerinde hiçbir etkisi yoktur, çünkü filtre zaten yapılmıştır. Yine Scala 2.8'de bu sorun kullanılarak çözülmüştür withFilter
. Zaman withFilter
kullanılır, bu durum bir eleman içinde erişilen her zaman değerlendirilir map
yöntem.
Referans : - s.120, Scala eylemde (Scala 2.10'u kapsar), Manning Yayınları, Milanjan Raychaudhuri - Odersky'nin anlamaya yönelik çeviri hakkındaki düşünceleri
Forall / var olmasının uygulanmamasının ana nedeni , kullanım durumunun şudur:
Forall / var uygulamak için şeyi için tembelliği kaybederek tüm unsurları elde etmemiz gerekir.
Yani mesela:
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'ın hala bir yineleyici olduğuna dikkat edin . Sadece dediğimiz zaman ToList rastgele sayılar üretilecek ve zincirde filtrelenecek
Not harita (kimlik) eşdeğerdir map (i => ı) ve orijinal türe withFilter nesne geri dönüştürmek için (örneğin bir koleksiyon, bir dere, bir yineleyici) kullanılır
Verim için kullanmak bir geçici çözüm olabilir, örneğin:
for {
e <- col;
if e isNotEmpty
} yield e.get(0)
Geçici bir çözüm olarak, diğer işlevleri yalnızca map
ve ile uygulayabilirsiniz flatMap
.
Dahası, bu optimizasyon küçük koleksiyonlarda işe yaramaz ...