Soru Scala'da bir liste yerine 'Iterator' oluşturmak için 'getiri' kullanmak mümkün mü?


Her değerin değerlendirilmesi yapılmadan verimi tekrarlayıcı olarak kullanmak mümkün mü?

Karmaşık bir liste oluşturmanın kolay olması ve daha sonra bunu dönüştürmeniz gerektiğinde yaygın bir görevdir. Iteratorçünkü bazı sonuçlara ihtiyacınız yok ...


28
2017-12-24 09:34


Menşei




Cevaplar:


Emin. Aslında, aşağıda listelediğim sıkı olmayanlık için üç seçenek var. Örnekler için şunları varsayın:

val list = List.range(1, 10)
def compute(n: Int) = {
    println("Computing "+n)
    n * 2
}
  1. Stream. bir Stream tembel olarak değerlendirilen bir listedir. Talep edilen değerleri hesaplayacaktır, ancak hesaplandıktan sonra değerleri yeniden hesaplamayacaktır. Akışın bölümlerini tekrar tekrar kullanacak olursanız en kullanışlı olanıdır. Örneğin, aşağıdaki kodu çalıştırarak "Computing 1", "Computing 2" ve "Computing 3", her defasında bir kez basacaktır.

    val stream = for (n <- list.toStream) yield compute(n)
    val third = stream(2)
    println("%d %d" format (third, stream(2)))
    
  2. bir görünüm. Bir görünüm, bir temel koleksiyon üzerindeki işlemlerin bir bileşimidir. Bir görünümü incelerken, incelenen her bir öğe talep üzerine hesaplanır. Bu görüşe rastgele erişirseniz, ancak asla bakmayacaksınız ama küçük bir kısmında. Örneğin, aşağıdaki kodun çalıştırılması iki kez "Hesaplama 3" ve başka bir şey (sonuç dışında, sonuç) yazdıracaktır.

    val view = for (n <- list.view) yield compute(n)
    val third = view(2)
    println("%d %d" format (third, view(2)))
    
  3. Iterator. bir Iterator Bir koleksiyonda tembelce yürümek için kullanılan bir şey. Konuşmak için bir "tek atış" koleksiyonu olarak düşünebilirsiniz. Herhangi bir unsuru yeniden hesaplayamaz veya saklayamaz - bir eleman "hesaplandığında", tekrar kullanılamaz. Bundan dolayı kullanmak biraz daha zordur, ancak bu kısıtlamalar verilen en verimli olanıdır. Örneğin, aşağıdaki örnek farklı olmalı çünkü Iterator indekslenmiş erişimi desteklemez (ve bu şekilde yazılırsa görünümü kötü yapar) ve aşağıdaki kod "Computing 1", "Computing 2", "Computing 3", "Computing 4", "Computing 5" ve "Computing 6" yazdırır. ". Ayrıca, sonunda iki farklı sayı basar.

    val iterator = for (n <- list.iterator) yield compute(n)
    val third = iterator.drop(2).next
    println("%d %d" format (third, iterator.drop(2).next))
    

48
2017-12-24 12:21





Tembel değerlendirmek istiyorsanız görünümleri kullanın, bkz. Görünümler.

Scala 2.8 Koleksiyonlar API'sı Scala koleksiyonlarını çok kullanacaksanız harika bir kitap.


3
2017-12-24 09:46





Benim bir List...

scala>  List(1, 2, 3)
res0: List[Int] = List(1, 2, 3)

Ve bir fonksiyon...

scala> def foo(i : Int) : String = { println("Eval: " + i); i.toString + "Foo" }
foo: (i: Int)String

Ve şimdi kullanacağım için-kavrama bir ile Iterator...

scala> for { i <- res0.iterator } yield foo(i)
res2: Iterator[java.lang.String] = non-empty iterator

Her türden anlama için kullanabilirsiniz flatMap, map ve filter yöntemleri. Ayrıca kullanabilirsiniz görünümler:

scala> for { i <- res0.view } yield foo(i)
res3: scala.collection.SeqView[String,Seq[_]] = SeqViewM(...)

Değerlendirme her iki durumda da katı değildir ...

scala> res3.head
Eval: 1
res4: String = 1Foo

2
2017-12-24 12:05