Die Funktion, nach der Sie suchen, wird normalerweise zipWith
genannt. Es ist leider nicht in den Standardbibliotheken zur Verfügung gestellt, aber es ist ziemlich einfach zu schreiben:
def zipWith[A,B,C](f: (A,B) => C, a: Iterable[A], b: Iterable[B]) =
new Iterable[C] {
def elements = (a.elements zip b.elements) map f.tupled
}
Diese nur einmal durchlaufen werden, da die Implementierungen für zip
und map
auf Iteratoren voll faul sind.
Aber warum aufhören bei Iterable
? Dies hat eine noch allgemeinere Form. Wir könnten eine Schnittstelle für alle Datenstrukturen deklarieren, die auf diese Weise gezippt werden können.
trait Zip[F[_]] {
def zipWith[A,B,C](f: (A,B) => C, a: F[A], b: F[B]): F[C]
}
Zum Beispiel können wir Funktionen zip:
trait Reader[A] {
type Read[B] = (A => B)
}
def readerZip[T] = new Zip[Reader[T]#Read] {
def zipWith[A,B,C](f: (A,B) => C, a: T => A, b: T => B): T => C =
(t: T) => f(a(t),b(t))
}
Es stellt sich heraus, ein noch allgemeiner Ausdruck dieser Art zu sein. Im Allgemeinen Typkonstruktoren, die eine Implementierung dieser Schnittstelle lassen sind applicative functors
trait Applicative[F[_]] {
def pure[A](a: A): F[A]
def map[A,B](f: A => B, a: F[A]): F[B]
def ap[A,B](f: F[A => B], a: F[A]): F[B]
}
Eine Implementierung von zipWith wird dann nur dies:
def zipWith[F[_],A,B,C](f: A => B => C, a: F[A], b: F[B])
(implicit m: Applicative[F]) =
m.ap(m.map(f,a), b)
Diese auf Funktionen jeder Stelligkeit verallgemeinert:
m.ap(m.ap(m.ap(m.map(f,a), b), c), d)
Die Bibliothek Scalaz bietet anwendungsspezifische Instanzen für viele Datenstrukturen in der Standardbibliothek. Außerdem wird eine bequeme Syntax für ap
bereitgestellt. In Scalaz heißt diese Funktion <*>
:
def zipWith[F[_]:Applicative,A,B,C](f: A => B => C, a: F[A], b: F[B]) =
(a map f) <*> b
Wenn 'zip()' nicht funktioniert, was brauchen Sie anders gemacht? –
Sohn eines ... zip. Richtig! Hab nicht mal daran gedacht. Warum postest du nicht, damit ich es aufbessern kann? – wheaties
Ich lasse @Mike antworten, aber Sie können 'list1 zip list2' und auch' (list1, list2) .zip' machen. Letzteres, nur Scala 2.8, erstellt keine temporäre Sammlung. Sie können auch 'list1.view zip list2' oder' list1.projection zip list2' auf Scala 2.8 bzw. 2.7 ausführen, um das Erstellen temporärer Sammlungen zu vermeiden. –