Domanda

Ho una raccolta che voglio mappare su una nuova raccolta, tuttavia ogni valore risultante dipende dal valore prima di essa in qualche modo. Potrei risolvere questo problema con una piega sinistra

val result:List[B] = (myList:List[A]).foldLeft(C -> List.empty[B]){ 
  case ((c, list), a) =>
    ..some function returning something like..
    C -> (B :: list)
} 

Il problema qui è che devo iterare l'intero elenco per recuperare l'elenco risultante. Suppongo che volevo una funzione che le maps TraversableOnce [A] per traversableOnce [B] e valutano solo i membri come li chiamo? Mi sembra un problema abbastanza convenzionale, quindi mi chiedo se esiste un approccio comune a questo. Quello che ho attualmente è:

implicit class TraversableOnceEx[T](val self : TraversableOnce[T]) extends AnyVal {

   def foldyMappyFunction[A, U](a:A)(func:(A,T) => (A,U)):TraversableOnce[U] = {
     var currentA = a
     self.map { t =>
        val result = func(currentA, t)
        currentA = result._1
        result._2
     }
   } 
}

Per quanto riguarda la purezza funzionale, non è possibile eseguirlo in parallelo, ma per il resto sembra solido.

Un esempio sarebbe; Restituimi ogni elemento e se è la prima volta che è apparso l'elemento prima.

val elements:TraversableOnce[E]
val result = elements.mappyFoldyFunction(Set.empty[E]) {
 (s, e) => (s + e) -> (e -> s.contains(e))
}
result:TraversableOnce[(E,Boolean)]
È stato utile?

Soluzione

Potresti essere in grado di utilizzare la Monade di Stato. Ecco il tuo esempio riscritto con Scalaz:

import scalaz._, Scalaz._

def foldyMappy(i: Int) = State[Set[Int], (Int, Boolean)](s => (s + i, (i, s contains(i))))

val r = List(1, 2, 3, 3, 6).traverseS(foldyMappy)(Set.empty[Int])._2

//List((1,false), (2,false), (3,false), (3,true), (6,false))
println(r)

Altri suggerimenti

Sembra che tu abbia bisogno Seqview. Uso view o view(from: Int, until: Int) Metodi per creare una visualizzazione non restringibile dell'elenco.

Davvero non capisco il tuo esempio in quanto il tuo controllo contiene ne deriverà sempre false.

foldLeft è diverso. Si tradurrà in un unico valore aggregando tutti gli elementi dell'elenco. Hai chiaramente bisogno map (List => List).

Comunque, rispondendo alla tua domanda sulla pigrizia: dovresti usare Stream invece di List. Stream Non valuta la coda prima di chiamarla effettivamente.

API di streaming

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top