Question

Je sais que les listes de Scala ont carte mise en œuvre avec (f: (A) => B):List[B] signature et foreach mise en œuvre avec (f: (A) => Unit):Unit signature mais je suis à la recherche de quelque chose qui accepte plusieurs iterables de la même manière que le Python map accepte plusieurs iterables.

Je cherche quelque chose avec une signature de (f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C] ou équivalent. Y at-il une bibliothèque où cela existe ou d'une manière comparable de faire semblable?

Edit:

Comme suggéré ci-dessous je pouvais faire

val output = myList zip( otherList ) map( x => x(0) + x(1) )

mais qui crée une liste temporaire entre les étapes. Si le commentor signalerait je pouvais lui upvote (indice, indice), mais est-il une autre façon?

Était-ce utile?

La solution

En scala 2.8, il existe une méthode appelée zippée dans Tuple2 et Tuple3 qui évitent de créer la collection temporaire. Voici quelques exemple d'utilisation cas:

Welcome to Scala version 2.8.0.r21561-b20100414020114 (Java HotSpot(TM) Client VM, Java 1.6.0_18).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val xs = 0 to 9
xs: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> val ys = List.range(0,10)
ys: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> val zs = Array.range(0,10)
zs: Array[Int] = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> (xs,ys).zipped.map{ _+_ }
res1: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 2, 4, 6, 8, 10, 12, 14, 16, 18)

scala> (zs,ys,xs).zipped.map{ _+_+_ }
res2: Array[Int] = Array(0, 3, 6, 9, 12, 15, 18, 21, 24, 27)

scala>

Il existe une méthode zip dans les deux Tuple2 et Tuple3. xs.zip (ys) est le même que (xs, ys) .zip

Remarque: Il y a aussi une pénurie (xs, ys) et (xs .zip, YS) .zipped, assurez-vous que xs ne peut pas être un INFINITE Stream. Aller à Ticket # 2634 pour plus d'informations. Je un poste en nabble.com il y a quelques jours qui montre mes opinions sur la façon de corriger ce billet.

Autres conseils

La fonction que vous recherchez est généralement appelé zipWith. Il est malheureusement pas fourni dans les bibliothèques standard, mais il est assez facile d'écrire:

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
  }

Cela traverse une seule fois, puisque les mises en œuvre pour zip et map sur itérateurs sont entièrement paresseux.

Mais pourquoi arrêt à Iterable? Cela a une forme encore plus générale. Nous pourrions déclarer une interface pour toutes les structures de données qui peuvent être compressés de cette façon.

trait Zip[F[_]] {
  def zipWith[A,B,C](f: (A,B) => C, a: F[A], b: F[B]): F[C]
}

Par exemple, on peut comprimer les fonctions:

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))
}

Il se révèle être une expression encore plus générale de ce type. En général, les constructeurs de type qui permettent une mise en œuvre de cette interface sont foncteurs applicatifs

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]
}

est alors une mise en œuvre de zipWith ceci:

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)

Ceci généralise aux fonctions de tout arité:

  m.ap(m.ap(m.ap(m.map(f,a), b), c), d)

La bibliothèque Scalaz fournit des cas Applicative pour un grand nombre de structures de données dans la bibliothèque standard . En outre, la syntaxe pratique est prévue pour ap. En Scalaz, cette fonction est appelée <*>:

def zipWith[F[_]:Applicative,A,B,C](f: A => B => C, a: F[A], b: F[B]) =
  (a map f) <*> b

Il y a une map2 méthode dans l'objet List à Scala 2.7 (et 2.8, mais il est dépréciée en faveur de zipped). Vous pouvez l'utiliser comme ceci:

List.map2( List(1,2,3) , List(4,5,6) ) { _ * _ }  // Gives List(4,10,18)

Eastsun est déjà montré comment utiliser zipped 2.8 (qui fonctionne sur toutes les collections, et pas seulement des listes).

Eh bien, je ne sais la (f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C] de syntaxe (et je sais que rien de Scala), mais si je devais deviner, cela signifierait « Une fonction < em> f prenant deux arguments itérables A et B et en retournant un iterable C ». Je ne sais pas si cela implique que tous les iterables donnent le même nombre d'éléments.

En Python, je pense que vous cherchez zip fonction :

>>> A = range(10, 15)
>>> B = range(1000, 1500, 100)
>>> zip(A, B)
[(10, 1000), (11, 1100), (12, 1200), (13, 1300), (14, 1400)]
>>> [a + b for a,b in zip(A, B)]
[1010, 1111, 1212, 1313, 1414]

La sortie de zip est seulement aussi longtemps que le plus court itérables:

>>> A=range(10, 12)
>>> zip(A, B)
[(10, 1000), (11, 1100)]

Quoi qu'il en soit, certaines fonctions Python intégré dans tout le monde a besoin de savoir, mais manque facilement: enumerate, map, reduce et zip. filter utilisé pour être sur cette liste, mais il est plus clair et plus souple d'utiliser une liste de compréhension ces jours-ci.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top