2016-09-15 1 views
1

J'ai une liste de chaînes que je suis en train de se scinder en listes séparées de manière séquentielle, regroupant l'occurrence 4-à-dire cette liste:liste des groupes en fonction des occurrences donnée dans Scala

val data = List("1", "2", "3", "4", "5", "6", "7", "8") 

doivent être classés comme

val list1 = List("1", "5") 
val list2 = List("2", "6") 
val list3 = List("3", "7") 
val list4 = List("4", "8") 

Je ne sais pas si je suis en train de overcomplicate cela, mais la seule façon que je peux penser est d'abord regrouper les éléments en utilisant par exemple sliding:

data.sliding(4,4).toList 

résultats dans

List(List(1, 2, 3, 4), List(5, 6, 7, 8)) 

puis à mettre en œuvre ma propre méthode unzip qui regrouperait ci-dessus comme ma sortie désirée.

S'il vous plaît quelqu'un peut-il me faire savoir s'il y a une façon plus facile de le faire?

+0

Ce serait génial si vous pouvez confirmer le comportement attendu pour les listes de plus de 8 éléments .... –

Répondre

3

Vous pouvez utiliser .transpose sur la liste .sliding génère:

scala> val data = List("1", "2", "3", "4", "5", "6", "7", "8") 
data: List[String] = List(1, 2, 3, 4, 5, 6, 7, 8) 

scala> data.sliding(4, 4).toList 
res1: List[List[String]] = List(List(1, 2, 3, 4), List(5, 6, 7, 8)) 

scala> data.sliding(4, 4).toList.transpose 
res2: List[List[String]] = List(List(1, 5), List(2, 6), List(3, 7), List(4, 8)) 
0

zip après sliding

scala> val data = List("1", "2", "3", "4", "5", "6", "7", "8") 
data: List[String] = List("1", "2", "3", "4", "5", "6", "7", "8") 

scala> val result = data.sliding(4, 4).toList 
result: List[List[String]] = List(List("1", "2", "3", "4"), List("5", "6", "7", "8")) 

scala> result.transpose 
res7: List[(String, String)] = List(("1", "5"), ("2", "6"), ("3", "7"), ("4", "8")) 
+0

Cela ne fonctionnera que si la liste contient exactement 8 éléments. –

0

Si tuples ferait en sortie, il est assez nette:

val tuples = data zip data.drop(4) 
//> tuples : List[(String, String)] = List((1,5), (2,6), (3,7), (4,8)) 

tour les dans List:

tuples.map{case(a,b) => List(a, b)} 
//> List[List[String]] = List(List(1, 5), List(2, 6), List(3, 7), List(4, 8)) 

EDIT: Montrer que le commentaire sur seulement travailler avec 8 est incorrect

def pairs[A](xs:List[A], n:Int) = 
(xs zip xs.drop(n)).map{case(a,b) => List(a, b)} 

pairs(List("1","2", "3", "4", "5", "6", "7", "8"), 4) 
// List(List(1, 5), List(2, 6), List(3, 7), List(4, 8)) 
pairs(List("1","2", "3", "4", "5", "6", "7", "8", "9"), 4) 
// List(List(1, 5), List(2, 6), List(3, 7), List(4, 8), List(5, 9)) 

pairs(List("1","2", "3", "4", "5", "6", "7", "8", "9", "10"), 4) 
// List(List(1, 5), List(2, 6), List(3, 7), List(4, 8), List(5, 9), List(6, 10)) 
pairs(List("1","2", "3", "4"), 4) 
// List() 
pairs(List("1","2", "3"), 4) 
// List() 
+0

Cette réponse nécessite également 'data' d'avoir exactement 8 éléments. –

+0

Je ne sais pas pourquoi vous dites cela, car ce n'est tout simplement pas vrai. –

+0

Si vous avez, par exemple, 'data = (1 à 12) .toList' vous allez retourner' Liste (Liste (1,5), Liste (2,6), Liste (3,7), Liste (4,8), Liste (5,9), ...) '; il ne s'agit pas de «diviser en listes séparées» comme dans la question, parce que vos résultats se recoupent. Si 'data = (1 à 4) .toList', vous renvoyez une liste vide. –

2

Une version qui fonctionnera pour chaque longueur de la liste:

def groupNth[A](n: Int, list: List[A]): List[List[A]] = { 
    val (firstN, rest) = list.splitAt(n) 
    val groupedRest = if (rest.nonEmpty) groupNth(n, rest) else Nil 
    // null.asInstanceOf[A] is of course cheating, but the value is never used 
    firstN.zipAll(groupedRest, null.asInstanceOf[A], Nil).map { 
    case (h, t) => h :: t 
    } 
} 


println(groupNth(4, Nil)) 
// List() 
println(groupNth(4, List(1, 2, 3))) 
// List(List(1), List(2), List(3)) 
println(groupNth(4, List(1, 2, 3, 4, 5, 6, 7, 8))) 
// List(List(1, 5), List(2, 6), List(3, 7), List(4, 8)) 
println(groupNth(4, List(1, 2, 3, 4, 5, 6, 7, 8, 9))) 
// List(List(1, 5, 9), List(2, 6), List(3, 7), List(4, 8)) 
println(groupNth(4, List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12))) 
// List(List(1, 5, 9), List(2, 6, 10), List(3, 7, 11), List(4, 8, 12))