2010-05-21 5 views
4

Je souhaite diviser une liste en "sous-nombres spécifiques".Division d'une liste en un nombre spécifique de sous-listes

C'est, par exemple si j'ai une liste List(34, 11, 23, 1, 9, 83, 5) et le nombre de sous-listes attendues est 3 alors je veux List(List(34, 11), List(23, 1), List(9, 83, 5)).

Comment procéder? J'ai essayé grouped mais il ne semble pas faire ce que je veux.

PS: Ce n'est pas une question de devoirs. Veuillez donner une solution directe plutôt que de vagues suggestions.

EDIT:

Un peu de changements dans les exigences ...

Étant donné une liste List(34, 11, 23, 1, 9, 83, 5) et le nombre de sous-listes = 3, je veux que la sortie soit List(List(34), List(11), List(23, 1, 9, 83, 5)). (c'est-à-dire 1 élément par liste excepté la dernière liste qui contient tous les éléments restants.)

Répondre

2

C'est un appel difficile, parce que vous ne savez pas combien d'éléments mettre dans chaque liste avant de connaître la taille de la liste . Si vous faire connaître la taille de la liste, vous pouvez utiliser regroupés: list.grouped((list.size + 2)/3).toList. Cependant, il ne divisera pas les éléments comme vous l'avez fait.

Question: est-ce que la commande est importante? Si l'ordre des éléments n'a pas besoin d'être préservé, alors il y a de meilleurs moyens d'y parvenir.

1

Si vous pouvez tolérer un appel pour obtenir la longueur de la liste, puis

l.grouped((l.length+2)/3).toList 

produira quelque chose de semblable à ce que vous voulez (si val l = List(34, 11, 23, 1, 9, 83, 5) vous obtiendrez List(List(34, 11, 23), List(1, 9, 83), List(5)) en arrière. Mais si vous voulez environ la distribution égale dans vos listes, alors vous devrez créer votre propre méthode pour le faire - il n'y a pas une fonction de bibliothèque qui partitionne une liste à parts égales en n

Quelque chose comme ça fonctionnerait, si vous voulez pour garder les pièces en ordre:

Et cela arrive à renvoyer exactement ce que vous voulez: List(List(34, 11), List(23, 1), List(9, 83, 5))
def chopList[T](
    l: List[T], pieces: Int, 
    len: Int = -1, done: Int = 0, waiting: List[List[T]]=Nil 
): List[List[T]] = { 
    if (l isEmpty) waiting.reverse 
    else { 
    val n = (if (len<0) l.length else len) 
    val ls = l.splitAt((n.toLong*(done+1)/pieces - n.toLong*done/pieces).toInt) 
    chopList(ls._2,pieces,n,done+1,ls._1 :: waiting) 
    } 
} 

Si vous ne voulez pas demander la longueur de la liste, vous pouvez écrire une méthode qui crée un groupe de compartiments et qui laisse tomber un nouvel élément dans chacun d'eux.

0

Ne le sait pas il répond à votre problème, mais ici un essai (qu'est-ce que vous attendez quand le compte est en dehors de la gamme)?

def group[T](list:List[T], count:Int):List[List[T]] = { 
    if (count <= 0 || count >= list.length) 
    List(list) 
    else { 
    val numElm = list.length/count 
    def loop(list:List[T], i:Int):List[List[T]] = { 
     i match { 
     case 0 => List(list) 
     case 1 => List(list) 
     case _ => { 
      val l = list.splitAt(numElm) 
      l._1 :: loop(l._2, i-1) 
     } 
     } 
    } 
    loop(list, count) 
    } 
} 
0

Est-ce que grouped est nouveau dans 2.8? Une solution pour selfmade 2.7.7 pourrait ressembler à ceci:

def splitTo (li: List [Int], count: Int) : List [List [Int]] = { 
    val size = li.length/count 

    if (count > 1) li.take (size) :: splitTo (li.drop (size), count-1) else 
     li :: Nil 
} 

Liste Paramétrage de [T] est laissée en excecise au lecteur.

+0

Oui, 'grouped' est nouvelle dans la bibliothèque Scala 2.8 collections. –

4

En réponse à vos besoins ont changé,

def splitN[A](list: List[A], n: Int): List[List[A]] = 
    if(n == 1) List(list) else List(list.head) :: splitN(list.tail, n - 1) 
Questions connexes