Pergunta

Eu sei que as listas do Scala têm um mapa implementação com assinatura (f: (A) => B):List[B] e um para cada implementação com assinatura (f: (A) => Unit):Unit mas estou procurando algo que aceite vários iteráveis ​​da mesma forma que o Python mapa aceita vários iteráveis.

Estou procurando algo com uma assinatura de (f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C] ou equivalente.Existe uma biblioteca onde isso existe ou uma maneira comparável de fazer algo semelhante?

Editar:

Como sugerido abaixo eu poderia fazer

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

mas isso cria uma lista temporária entre as etapas.Se o comentarista postasse, eu poderia votar nele (dica, dica), mas existe outra maneira?

Foi útil?

Solução

No scala 2.8, existe um método chamado zipado em Tuple2 e Tuple3 que evita a criação de uma coleção temporária.Aqui está um exemplo de caso de uso:

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>

Existe um método zip em Tuple2 e Tuple3.xs.zip(ys) é o mesmo que (xs,ys).zip

Observação: Também há alguma escassez em (xs,ys).zip e (xs,ys).zipped, certifique-se de que xs não pode ser um fluxo INFINITO.Vá para Bilhete #2634 Para maiores informações.Eu tenho uma postagem em nabble.com há alguns dias, que mostra minhas opiniões sobre como corrigir esse ticket.

Outras dicas

A função que você está procurando geralmente é chamada zipWith.Infelizmente, não é fornecido nas bibliotecas padrão, mas é muito fácil de escrever:

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
  }

Isso será percorrido apenas uma vez, já que as implementações para zip e map em iteradores são totalmente preguiçosos.

Mas por que parar em Iterable?Isto tem uma forma ainda mais geral.Poderíamos declarar uma interface para todas as estruturas de dados que podem ser compactadas dessa forma.

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

Por exemplo, podemos compactar funções:

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

Acontece que existe uma expressão ainda mais geral deste tipo.Em geral, os construtores de tipo que permitem uma implementação desta interface são funtores aplicativos

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

Uma implementação de zipWith é apenas isto:

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)

Isso generaliza para funções de qualquer aridade:

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

O escalaz A biblioteca fornece instâncias de aplicativos para muitas estruturas de dados na biblioteca padrão.Além disso, uma sintaxe conveniente é fornecida para ap.No Scalaz, esta função é chamada <*>:

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

Existe um método map2 no List objeto no Scala 2.7 (e 2.8, mas está obsoleto em favor de zipped).Você usa assim:

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

Eastsun já mostrou como usar zipped em 2.8 (que funciona em todas as coleções, não apenas em listas).

Bem, eu não saber a sintaxe (f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C] (e eu sei nada de Scala), mas se eu tivesse que adivinhar, significaria "Uma função f pegando dois argumentos iteráveis A e B e retornando um iterável C".Não tenho certeza se isso implica que todos os iteráveis ​​produzem o mesmo número de itens.

Em Python, acho que você está procurando o fecho eclair função:

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

zipA saída de é tão longa quanto o iterável mais curto:

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

De qualquer forma, algumas funções internas do Python que todos precisam saber, mas facilmente perdem: enumerate, map, reduce, e zip. filter costumava estar nessa lista, mas hoje em dia é mais claro e flexível usar uma compreensão de lista.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top