Compte tenu de la liste Scala suivante:
val l = List(List("a1", "b1", "c1"), List("a2", "b2", "c2"), List("a3", "b3", "c3"))
Comment puis-je avoir:
List(("a1", "a2", "a3"), ("b1", "b2", "b3"), ("c1", "c2", "c3"))
Puisque zip ne peut être utilisé que pour combiner deux listes, je pense que vous auriez besoin d'itérer / réduire la liste principale d'une manière ou d'une autre. Sans surprise, ce qui suit ne fonctionne pas:
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)
Des suggestions pour faire cela? Je pense qu'il me manque un moyen très simple de le faire.
Mise à jour: je recherche une solution qui peut prendre une liste de N listes avec M éléments chacune et créer une liste de M TupleNs.
Mise à jour 2: En fait, il est préférable pour mon cas d'utilisation spécifique d'avoir une liste de listes, plutôt qu'une liste de tuples, donc j'accepte la réponse de Pumpkin. C'est aussi le plus simple, car il utilise une méthode native.
scala
functional-programming
list
zip
pr1001
la source
la source
Réponses:
Je ne pense pas qu'il soit possible de générer une liste de tuples de taille arbitraire, mais la fonction de transposition fait exactement ce dont vous avez besoin si cela ne vous dérange pas d'obtenir une liste de listes à la place.
la source
HList
s et autres.Pour référence future.
la source
zipped
n'est pas une fonction deList
.zipped
est obsolète dans Scala 2.13. en 2.13, fairel1.lazyZip(l2).lazyZip(l3).toList
Donc, ce morceau de code ne répondra pas aux besoins de l'OP, et pas seulement parce qu'il s'agit d'un fil de discussion vieux de quatre ans, mais il répond à la question du titre, et peut-être que quelqu'un pourrait même le trouver utile.
Pour zipper 3 collections:
la source
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) }
Oui, avec zip3 .
la source
transpose
fait l'affaire. Un algorithme possible est:Par exemple:
La réponse est tronquée à la taille de la liste la plus courte dans l'entrée.
la source
def combineLists[A](ss:List[A]*) = { val sa = ss.reverse; (sa.head.map(List(_)) /: sa.tail)(_.zip(_).map(p=>p._2 :: p._1)) }
Scala traite toutes ses différentes tailles de tuple que différentes classes (
Tuple1
,Tuple2
,Tuple3
,Tuple4
, ...,Tuple22
) alors qu'ils font tout Hériter duProduct
trait, ce trait ne porte pas suffisamment d' informations pour utiliser réellement les valeurs de données des différentes tailles de tuples s'ils pouvaient tous être retournés par la même fonction. (Et les génériques de scala ne sont pas non plus assez puissants pour gérer ce cas.)Votre meilleur pari est d'écrire des surcharges de la fonction zip pour les 22 tailles de Tuple. Un générateur de code vous aiderait probablement.
la source
Si vous ne voulez pas suivre la route applicative scalaz / cats / (insérez votre bibliothèque fonctionnelle préférée ici), la correspondance de motifs est la voie à suivre, bien que la
(_, _)
syntaxe soit un peu gênante avec l'imbrication, changeons-la:le
&
un choix arbitraire ici, tout ce qui a l'air sympa devrait le faire. Cependant, vous aurez probablement quelques sourcils levés lors de la révision du code.Cela devrait également fonctionner avec tout ce que vous pouvez
zip
(par exemple,Future
s)la source
Je ne crois pas que ce soit possible sans être répétitif. Pour une raison simple: vous ne pouvez pas définir le type de retour de la fonction que vous demandez.
Par exemple, si votre entrée était
List(List(1,2), List(3,4))
, alors le type de retour seraitList[Tuple2[Int]]
. S'il avait trois éléments, le type de retour seraitList[Tuple3[Int]]
, et ainsi de suite.Vous pourriez revenir
List[AnyRef]
, ou mêmeList[Product]
, puis faire un tas de cas, un pour chaque condition.En ce qui concerne la transposition générale de la liste, cela fonctionne:
la source
c
en ligne aveca
ou avecb
? Et comment le représenteriez-vous en ligne avec l'autre?c
est en ligne aveca
(c'est-à-dire en ligne avec index)?product-collections a une
flatZip
opération jusqu'à l'arité 22.la source
Avec Scalaz:
Pour plus de 5:
la source