Pregunta

Yo sé que las listas de Scala tienen un mapa aplicación con (f: (A) => B):List[B] firma y una foreach aplicación con la firma (f: (A) => Unit):Unit pero estoy buscando algo que acepta múltiples iterables de la misma manera que el pitón mapa acepta múltiples iterables.

Estoy buscando algo, con una firma de (f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C] o equivalente. ¿Hay una biblioteca siempre que exista o una manera de hacer comparables similar?

Editar:

Como se sugiere a continuación que podía hacer

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

sino que crea una lista temporal entre los pasos. Si el commentor registraría que él (pista, pista) pudiera upvote pero ¿hay otra forma?

¿Fue útil?

Solución

En Scala 2.8, hay un método llamado cremallera en Tuple2 y Tuple3 que eviten crear colección temporal. He aquí algunos casos de uso de ejemplo:

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>

Hay un método de cremallera tanto en Tuple2 y Tuple3. xs.zip (ys) es lo mismo que (xs, ys) .zip

Nota: Hay también una cierta escasez de (xs, ys) .zip y (xs, ys) .zipped, asegúrese de que x no puede ser un flujo infinito. Ir a Ticket # 2634 para más información. Tengo un post en nabble.com hace unos días, que muestra mis opiniones sobre cómo solucionar este billete.

Otros consejos

La función que está buscando es usualmente llamado zipWith. Lamentablemente no está previsto en las bibliotecas estándar, pero es bastante fácil de escribir:

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
  }

Esto atravesar una sola vez, ya que las implementaciones para zip y map en iteradores son totalmente perezoso.

Pero por qué parada en Iterable? Esto tiene una forma aún más general. Podríamos declarar una interfaz para todas las estructuras de datos que puede ser comprimido de esta manera.

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

Por ejemplo, podemos comprimir funciones:

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

No resulta ser una expresión más general de este tipo. En general, los constructores de tipos que permiten una implementación de esta interfaz son aplicativo funtores

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

Una implementación de zipWith es simplemente esto:

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)

Este generaliza a funciones de cualquier aridad:

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

El Scalaz biblioteca proporciona casos aplicativos para una gran cantidad de estructuras de datos en la biblioteca estándar . Además, se proporciona la sintaxis conveniente para ap. En Scalaz, esta función se llama <*>:

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

Hay una map2 método en el objeto List en Scala 2.7 (y 2.8, pero está desfasada y en zipped). Lo usa de esta manera:

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

de Eastsun que se muestran cómo utilizar zipped en 2.8 (que funciona en todas las colecciones, no sólo las listas).

Bueno, no me sabe (f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C] la sintaxis (y sé no de Scala), pero si tuviera que adivinar, que significaría "Una función < em> f tomar dos argumentos iterables A y B y devolver un iterable C ". No estoy seguro de si esto implica que todos los iterables dan el mismo número de elementos.

En Python, creo que estás en busca de la zip función :

>>> 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 producción de zip es sólo el tiempo que el menor iterable:

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

De todas formas, algunas de ellas construidas en Python necesidades funciones que cada uno supiera, pero no alcanza fácilmente: enumerate, map, reduce y zip. filter utiliza para estar en esa lista, pero es más clara y más flexible de usar una lista por comprensión en estos días.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top