2010-07-30 5 views
29

Je voulais ajouter des éléments de manière dynamique dans un tableau. Mais il semble que les tableaux et les listes Scala ne fournissent aucune méthode pour ajouter dynamiquement des éléments en raison de la nature immuable.Quelle est la meilleure façon de créer un tableau dynamique dans Scala?

J'ai donc décidé d'utiliser le type de données List pour utiliser cette méthode :: pour y parvenir. Mon apparence de code comme ceci

var outList = List(Nil) 
val strArray = Array("ram","sam","bam") 

for (str<-strArray) 
    outList = str :: outList 

Bien que cela fonctionne d'une certaine façon, le problème est que les nouvelles chaînes sont pré-joint dans la liste. Mais l'exigence idéale est l'ordre des données. Oui, je sais ce que vous pensez, vous pouvez inverser la liste des résultats finaux pour obtenir l'ordre d'origine. Mais le problème est que c'est un énorme tableau. Et je crois que ce n'est pas une solution bien qu'elle résout le problème. Je crois qu'il devrait y avoir un moyen simple de résoudre ce problème ...

Et ma raison pour le piratage de Scala est d'apprendre la manière fonctionnelle de codage. Ayant var (type mutable) et peupler la liste à la volée me semble n'est pas une manière fonctionnelle de résoudre les choses.

Comment puis-je le faire?

Idéalement, je veux réaliser quelque chose comme ça dans Scala (ci-dessous le code C#)

List<int> ls = new List<int>();  
for (int i = 0; i < 100; i++) 
    ls.Add(i); 

Répondre

29

Mais il semble que Scala Arrays & Listes ne fournit aucune méthode pour ajouter des éléments dynamiquement en raison de la nature immuable.

Bien, non. Scala Les tableaux ne sont que des tableaux Java, de sorte qu'ils sont mutable:

val arr = Array(1,2) 

arr(0) = 3 // arr == Array(3, 2) 

Mais tout comme Java (et C/C++/C#/etc.) Des tableaux, vous ne pouvez pas changer la taille d'un tableau .

Vous avez donc besoin d'une autre collection, qui est soutenue par un tableau, mais qui autorise le redimensionnement. Une collection adaptée à Scala est scala.collection.mutable.ArrayBuffer, java.util.ArrayList en Java, etc.

Si vous voulez obtenir un List au lieu d'un Array à la fin, utilisez scala.collection.mutable.ListBuffer à la place.

+4

merci .. "ListBuffer" est celui que je voulais .. :) – RameshVel

3

D'accord, il y a quelques petites choses à éclaircir.

Ceci est faux, vous faites une liste d'éléments d'un, contenant une liste vide:

scala> var outList = List(Nil) 
outList: List[object Nil] = List(List()) 

Nil est la liste vide:

scala> var outList: List[String] = Nil 
outList: List[String] = List() 

Ou, si vous préférez:

scala> var outList = List[String]() 
outList: List[String] = List() 

Sans plus de contexte, il est difficile de savoir ce que vous entendez par «dynamiquement». Votre exemple de code serait mieux écrit:

scala> val strArray = Array("ram","sam","bam") 
strArray: Array[java.lang.String] = Array(ram, sam, bam) 

scala> strArray toList 
res0: List[java.lang.String] = List(ram, sam, bam) 

Si vous voulez une collection mutable qui peut se développer et gérer efficacement précédez, ajouter et insérer des opérations, vous pouvez utiliser scala.mutable.Buffer.

+1

Veuillez ajouter une mise en forme aux 2 exemples au milieu. –

+0

dynamiquement dans le sens "je veux remplir la liste à la volée". la taille est inconnue. Ce pourrait être n'importe quoi basé sur les données entrantes ..J'ai mis à jour ma question pour plus de clarté – RameshVel

3

Aller après la réponse de retronym:

Si vous voulez continuer à utiliser la liste il y a quelques façons de PREPEND un élément à la liste. Qu'est-ce que vous pouvez faire est (oui la partie supérieure est toujours incorrecte):

scala> var outList : List[String] = Nil 
outList: List[String] = List() 

scala> val strArray = Array("a","b","c") 
strArray: Array[java.lang.String] = Array(a, b, c) 

scala> for(s <- strArray)  
    | outList = outList :+ s 

scala> outList 
res2: List[String] = List(a, b, c) 

Notez le: + opérateur. Si vous préférez ajouter, vous utiliserez s +: outList.

Maintenant, qui dit que programmer en Scala n'est pas amusant? ;)

P.S. Peut-être que la raison pour laquelle vous voulez les rendre immuables est la vitesse. La gestion de grandes quantités de données sera plus efficace avec des types de données immuables. Ai-je raison?

+0

Notez que 'for (s <- strArray) {outList = outList: + s}' prend un temps quadratique. –

+0

Ahh, foutu! Vraiment? Qu'en est-il de outList ::: s? Avez-vous une référence sur la complexité des fonctions scala? J'ai essayé de googler n'a rien trouvé. De http://stackoverflow.com/questions/1241166/preferred-way-to-create-a-scala-list Je pense que le consensus général est de préfixer et inverser. –

+1

Même. 'List' est une liste liée immuable, ajoutant ainsi 1 élément à un - quelle que soit la méthode que vous utilisez - _a prendre_ un temps linéaire (puisque vous devez copier tous ses éléments), donc cette boucle prend un temps quadratique. Il est préférable d'ajouter 'ListBuffer' et d'appeler' toList' plutôt que d'ajouter ou de reculer, mais il vaut mieux beaucoup plus de préfixer et d'inverser que d'ajouter 'List'. –

4

Si vous souhaitez utiliser un tampon mutable, comme mentionné précédemment. Il ressemble à ceci:

scala> var outList = scala.collection.mutable.Buffer[String]() 
outList: scala.collection.mutable.Buffer[String] = ArrayBuffer() 

scala> for(str<-strArray) outList += str       

scala> outList 
res10: scala.collection.mutable.ListBuffer[String] = ListBuffer(ram, sam, bam) 

Quoi qu'il en soit, peut-être il est préférable de faire directement les choses que vous voulez faire avec le strArray. Par exemple:

strArray map(_.toUpperCase) foreach(println) 
4

Si vous voulez travailler avec des structures immuables, vous pouvez utiliser la méthode ++:

scala> val orgList = List(1,2,3) 
orgList: List[Int] = List(1, 2, 3) 

scala> val list2Add = List(4,5,6) 
list2Add: List[Int] = List(4, 5, 6) 

scala> val newList = orgList ++ list2Add 
newList: List[Int] = List(1, 2, 3, 4, 5, 6) 

Si vous voulez faire plus de travail sur les éléments que simplement les ajouter, vous pouvez utiliser les fonctions supérieures de l'ordre:

val newList = orgList ++ list2Add.map(_ * 2) 
newList: List[Int] = List(1, 2, 3, 8, 10, 12) 

Ou avec une boucle:

val newList = orgList ++ {for(x <- list2Add) yield 2*x} 

Ou vous pouvez créer une boucle récursive:

def addAll(toList: List[Int], fromList: List[Int]): List[Int] = 
    fromList match { 
    case x :: tail => addAll(2*x :: toList, tail) 
    case Nil => toList 
    } 

val newList = addAll(orgList, list2Add) 

mais dans ce cas, l'ordre des éléments ajoutés sera inversée:

List(12, 10, 8, 1, 2, 3) 

Si vous voulez des performances lorsque vous travaillez avec des listes, il est mieux vaut inverser le résultat que d'essayer d'ajouter de nouveaux éléments à la fin. Ajout d'éléments à la fin d'une liste est bonne nooot :-)

+0

ce n'est pas obligatoire ... je veux remplir la liste à la volée ".la taille est inconnue.Il pourrait être quelque chose basé sur les données entrantes .. J'ai mis à jour ma question pour plus de clarté – RameshVel

2

Si vous cherchez à créer une nouvelle collection, vous pouvez utiliser le mot clé de rendement:

val outlist = for(i <- 0 to 100) yield i 

Ou:

val arrList = "Some" :: "Input" :: "List" :: Nil 
val outlist = for (i <- arrList) yield i 

Techniquement, outlist est un Seq dans les deux exemples ci-dessus. Il se peut donc que vous deviez appeler la méthode toList si vous avez besoin de certaines méthodes de List.

+1

Vous n'avez même pas besoin de dire 'for (i <- 0 à 100) yield i' Vous pouvez juste dire' (0 à 100) 'et, si vous le souhaitez, le convertir en une collection différente avec la méthode '.toList' ou similaire. –

Questions connexes