filtre yerine withFilter


Yanıtlar:


122

Gönderen Scala docs :

Not: arasındaki fark c filter pve c withFilter pikincisi sadece müteakip etki alanını kısıtladığı oysa eski yeni koleksiyon oluşturur olmasıdır map, flatMap, foreach, ve withFilteroperasyonlar.

Böylece filter, orijinal koleksiyonu alacak ve yeni bir koleksiyon üretecek, ancak (filtrelenmiş) koleksiyondan ikinci bir geçişi koruyarak, withFilterfiltrelenmemiş 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, withFilterbu 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 FilterMonadicdönüş türüne eklenmemişlerdir withFilter.


Umarım bir gün hala bu yöntemleri eklerler.
Kigyo

1
@Kigyo KendinizleFilter'i kullanmanız gerektiğini düşünmüyorum (for-ifadeleri içinde örtük olarak dışında). viewHaritaların / filtrelerin tembel olmasını istiyorsanız kullanın .
Luigi Plinge

Anlıyorum. Nedir arasındaki kesin fark viewve withFilter? Görünüm neden kullanılmıyor for-loops?
Kigyo

5
Sadece referans için, Koleksiyonlar - İpuçları ve Püf Noktalarının olağanüstü bilgiler sağladığını düşünüyorum . H5'ler sabitlenmemiştir, ancak Don’t create temporary collectionsbağlantılı bölümde arama yapabilirsiniz .
sthzg

4
Açıkça kullanımıyla ilgili olarak 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 pvs. seq withFilter p.
Chuck Daniels

9

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 resulteş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 resultoldukça farklı olacaktır: List(1, 2, 3). goBayrak oluşturmamızın falsefiltre ü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 withFilterkullanılır, bu durum bir eleman içinde erişilen her zaman değerlendirilir mapyö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


1

Forall / var olmasının uygulanmamasının ana nedeni , kullanım durumunun şudur:

  • Filtre ile tembel bir şekilde sonsuz bir akışa / tekrarlanabilir
  • Filtre ile tembel olarak başka bir tane uygulayabilirsiniz (ve tekrar tekrar)

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


1

Forall / var bölümü için:

someList.filter(conditionA).forall(conditionB)

aynı olacaktır (biraz sezgisel olmasa da)

!someList.exists(conditionA && !conditionB)

Benzer şekilde, .filter () .evcut () tek bir var () denetimi içinde birleştirilebilir



-5

Geçici bir çözüm olarak, diğer işlevleri yalnızca mapve ile uygulayabilirsiniz flatMap.

Dahası, bu optimizasyon küçük koleksiyonlarda işe yaramaz ...

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.