Dada la siguiente lista de Scala:
val l = List(List("a1", "b1", "c1"), List("a2", "b2", "c2"), List("a3", "b3", "c3"))
Como puedo conseguir:
List(("a1", "a2", "a3"), ("b1", "b2", "b3"), ("c1", "c2", "c3"))
Dado que zip solo se puede usar para combinar dos Listas, creo que necesitaría iterar / reducir la Lista principal de alguna manera. No es de extrañar que lo siguiente no 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)
¿Alguna sugerencia de cómo hacer esto? Creo que me falta una forma muy sencilla de hacerlo.
Actualización: Estoy buscando una solución que pueda tomar una Lista de N Listas con M elementos cada una y crear una Lista de M TupleN.
Actualización 2: resulta que es mejor para mi caso de uso específico tener una lista de listas, en lugar de una lista de tuplas, por lo que acepto la respuesta de calabaza. También es el más simple, ya que utiliza un método nativo.
scala
functional-programming
list
zip
pr1001
fuente
fuente
Respuestas:
No creo que sea posible generar una lista de tuplas de tamaño arbitrario, pero la función de transposición hace exactamente lo que necesita si no le importa obtener una lista de listas en su lugar.
fuente
HList
s y similares.Para futura referencia.
fuente
zipped
no es una función deList
.zipped
está obsoleto en Scala 2.13. en 2.13, hacerl1.lazyZip(l2).lazyZip(l3).toList
Entonces, este fragmento de código no responderá a las necesidades del OP, y no solo porque se trata de un hilo de cuatro años, sino que responde a la pregunta del título, y tal vez a alguien incluso le resulte útil.
Para comprimir 3 colecciones:
fuente
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) }
Sí, con zip3 .
fuente
transpose
Hace el truco. Un posible algoritmo es:Por ejemplo:
La respuesta se trunca al tamaño de la lista más corta de la entrada.
fuente
def combineLists[A](ss:List[A]*) = { val sa = ss.reverse; (sa.head.map(List(_)) /: sa.tail)(_.zip(_).map(p=>p._2 :: p._1)) }
Golosinas Scala todos sus diferentes tamaños de tupla como diferentes clases (
Tuple1
,Tuple2
,Tuple3
,Tuple4
, ...,Tuple22
), mientras que lo hacen todos heredan de laProduct
característica, rasgo que no lleva suficiente información para utilizar realmente los valores de datos de los diferentes tamaños de las tuplas si todos pudieran ser devueltos por la misma función. (Y los genéricos de Scala tampoco son lo suficientemente potentes para manejar este caso).Su mejor opción es escribir sobrecargas de la función zip para los 22 tamaños de tuplas. Un generador de código probablemente te ayudaría con esto.
fuente
Si no desea seguir la ruta aplicativa scalaz / cats / (inserte su biblioteca funcional favorita aquí), la coincidencia de patrones es el camino a seguir, aunque la
(_, _)
sintaxis es un poco incómoda con el anidamiento, así que cambiémosla:El
&
es una elección arbitraria aquí, cualquier cosa que se ve bien infija debe hacerlo. Sin embargo, es probable que levante algunas cejas durante la revisión del código.También debería funcionar con todo lo que pueda
zip
(por ejemplo,Future
s)fuente
No creo que eso sea posible sin ser repetitivo. Por una simple razón: no puede definir el tipo de retorno de la función que está solicitando.
Por ejemplo, si su entrada fue
List(List(1,2), List(3,4))
, entonces el tipo de retorno seríaList[Tuple2[Int]]
. Si tuviera tres elementos, el tipo de retorno seríaList[Tuple3[Int]]
, y así sucesivamente.Puede regresar
List[AnyRef]
, o inclusoList[Product]
, y luego hacer un montón de casos, uno para cada condición.En cuanto a la transposición general de la lista, esto funciona:
fuente
c
en línea cona
o conb
? ¿Y cómo lo representaría en línea con el otro?c
está en línea cona
(es decir, en línea con el índice)?colecciones de productos tiene una
flatZip
operación hasta aridad 22.fuente
Con Scalaz:
Por más de 5:
fuente