Dada a seguinte Lista de Scala:
val l = List(List("a1", "b1", "c1"), List("a2", "b2", "c2"), List("a3", "b3", "c3"))
Como posso obter:
List(("a1", "a2", "a3"), ("b1", "b2", "b3"), ("c1", "c2", "c3"))
Como zip só pode ser usado para combinar duas Listas, acho que você precisaria iterar / reduzir a Lista principal de alguma forma. Não é de surpreender que o seguinte não funcione:
scala> l reduceLeft ((a, b) => a zip b)
<console>:6: error: type mismatch;
found : List[(String, String)]
required: List[String]
l reduceLeft ((a, b) => a zip b)
Alguma sugestão de como fazer isso? Acho que estou perdendo uma maneira muito simples de fazer isso.
Atualização: Estou procurando uma solução que pode pegar uma Lista de N Listas com M elementos cada e criar uma Lista de M TupleNs.
Atualização 2: Acontece que é melhor para meu caso de uso específico ter uma lista de listas, em vez de uma lista de tuplas, então estou aceitando a resposta do pumpkin. Também é o mais simples, pois usa um método nativo.
scala
functional-programming
list
zip
pr1001
fonte
fonte
Respostas:
Não acredito que seja possível gerar uma lista de tuplas de tamanho arbitrário, mas a função transpor faz exatamente o que você precisa se você não se importar em obter uma lista de listas.
fonte
HList
s e semelhantes.Para referência futura.
fonte
zipped
não é uma função deList
.zipped
está obsoleto no Scala 2.13. em 2.13, façal1.lazyZip(l2).lazyZip(l3).toList
Portanto, este trecho de código não atenderá às necessidades do OP, e não apenas porque este é um segmento de quatro anos, mas responde à pergunta do título e talvez alguém possa até achar útil.
Para compactar 3 coleções:
fonte
as zip bs zip cs zip ds map { case ((a,b),c)} map {case ((a,b),c,d)=>(a,b,c,d)}
as zip bs zip cs zip ds map {case (((a,b),c),d)=>(a,b,c,d) }
Sim, com zip3 .
fonte
transpose
faz o truque. Um algoritmo possível é:Por exemplo:
A resposta é truncada para o tamanho da lista mais curta na entrada.
fonte
def combineLists[A](ss:List[A]*) = { val sa = ss.reverse; (sa.head.map(List(_)) /: sa.tail)(_.zip(_).map(p=>p._2 :: p._1)) }
Trata Scala todos os seus diferentes tamanhos tupla como diferentes classes (
Tuple1
,Tuple2
,Tuple3
,Tuple4
, ...,Tuple22
) enquanto eles fazem tudo herdar doProduct
traço, essa característica não carrega informação suficiente para realmente usar os valores de dados entre os diferentes tamanhos de tuples se eles pudessem ser todos retornados pela mesma função. (E os genéricos do scala também não são poderosos o suficiente para lidar com este caso.)Sua melhor aposta é escrever sobrecargas da função zip para todos os 22 tamanhos de tupla. Um gerador de código provavelmente o ajudaria com isso.
fonte
Se você não quiser seguir a rota do aplicativo scalaz / cats / (insira sua biblioteca funcional favorita aqui), a correspondência de padrões é o caminho a percorrer, embora a
(_, _)
sintaxe seja um pouco estranha com aninhamento, então vamos mudá-la:O
&
é uma escolha arbitrária aqui, qualquer coisa que pareça um bom infixo deve servir. Provavelmente, você ficará surpreso durante a revisão do código.Também deve funcionar com qualquer coisa que você puder
zip
(por exemplo,Future
s)fonte
Não acredito que seja possível sem ser repetitivo. Por um motivo simples: você não pode definir o tipo de retorno da função que está solicitando.
Por exemplo, se sua entrada foi
List(List(1,2), List(3,4))
, o tipo de retorno seriaList[Tuple2[Int]]
. Se tivesse três elementos, o tipo de retorno seriaList[Tuple3[Int]]
, e assim por diante.Você poderia retornar
List[AnyRef]
, ou até mesmoList[Product]
, e então fazer um monte de casos, um para cada condição.Quanto à transposição geral da Lista, funciona:
fonte
c
alinhado coma
ou comb
? E como você representaria estar alinhado com o outro?c
está alinhado coma
(ou seja, alinhado com o índice)?a coleção de produtos tem uma
flatZip
operação até aridade 22.fonte
Com Scalaz:
Por mais de 5:
fonte