2009-09-18 8 views
12

Je veux copier superficiellement une liste dans Scala.Comment copier une liste dans Scala

que je voulais faire somehing comme:

val myList = List("foo", "bar") 
val myListCopy = myList.clone 

Mais la méthode clone est protégé.

+0

Cela ne serait-il pas en rapport avec http://stackoverflow.com/questions/1267261/does-scala-anyref-clone-perform-a-shallow-or-deep-copy? – VonC

+12

Pour quoi faire? Les objets de liste sont immuables. –

+1

Je voulais supprimer un élément de la liste (en utilisant la méthode remove (A => Boolean) dans une boucle. (Note: J'ai commencé Scala il y a 2 heures :)) – Maxime

Répondre

6

Pour filtrer une liste:

val list = List(1,2,3,4,5) 
//only evens 
val evens = list.filter(e=>e%2 == 0) 

println(list) 
//--> List(1, 2, 3, 4, 5) 

println(evens) 
//--> List(2, 4) 

Vous pouvez également utiliser le caractère générique pour sauver quelques caractères:

val evens = list.filter(_%2==0) 

Notez que, comme commenté ci-dessus, les listes sont immuables. Cela signifie que ces opérations ne modifient pas la liste d'origine, mais en réalité créent une nouvelle liste.

13

Voici une non-réponse: ne faites pas cela. Un List est immuable, donc il n'y a absolument aucun intérêt à en copier un.

Considérons quelques opérations:

val list = List(1,2,3) 
val l1 = 0 :: list 
val l2 = "a" :: list 

Ni l1 ni l2 modifient list, mais ils ont tous deux créer de nouvelles listes qui font référence à list.

Expliquons ceci en détail. Le constructeur List(1,2,3) crée trois éléments et utilise également un objet singleton. Plus précisément, il est instancié ces éléments:

::(3, Nil) 
::(2, reference to the previous element) 
::(1, reference to the previous element) 

Et Nil est un objet singleton. Ce que l'identificateur list désigne réellement est ce dernier élément.

Maintenant, lorsque vous attribuez 0 :: list-l1, vous instanciez un nouvel objet:

::(0, reference to ::(1, etc)) 

Bien sûr, car il y a une référence à list, vous pouvez penser à l1 comme une liste de quatre éléments (ou cinq, si vous comptez Nil).

Maintenant, l2 n'est même pas du même type de list, mais il le référence aussi! Ici:

::("a", reference to ::(1, etc)) 

Le point important à propos de tous ces objets est qu'ils ne peuvent pas être modifiés. Il n'y a pas de setters, ni de méthodes qui vont changer l'une de leurs propriétés. Ils auront toujours les mêmes valeurs/références dans leur «tête» (c'est ce que nous appelons le premier élément), et les mêmes références dans leur «queue» (c'est ce que nous appelons le second élément).

Cependant, il existe des méthodes qui semblent comme ils changent la liste. Soyez assuré, cependant, qu'ils créent nouvelles listes.Par exemple:

val l3 = list map (n => n + 1) 

La carte méthode crée une liste entièrement nouvelle, de la même taille, où nouvel élément peut être calculé à partir d'un élément correspondant dans list (mais vous pourriez ignorer l'ancien élément aussi).

val l4 = l2 filter (n => n.isInstanceOf[Int]) 

Alors que l4 a les mêmes éléments que list (mais un autre type), il est également une liste complètement nouvelle. La méthode filter crée une nouvelle liste, basée sur une règle que vous transmettez pour lui indiquer les éléments qui entrent et ceux qui ne le font pas. Il n'essaie pas d'optimiser au cas où pourrait retourner une liste existante.

val l5 = list.tail 

Ceci ne crée pas une nouvelle liste. Au lieu de cela, il attribue simplement à l5 un élément existant de list.

val l6 = list drop 2 

Encore une fois, aucune nouvelle liste créée.

val l7 = list take 1 

Ceci, cependant, crée une nouvelle liste, précisément parce qu'il ne peut pas changer le premier élément de list de sorte que ses points de queue à Nil.

est ici quelques détails de mise en œuvre supplémentaires:

  • List est une classe abstraite. Il a deux descendants, la classe :: (oui, c'est le nom de la classe), et l'objet singleton Nil. List est scellé, donc vous ne pouvez pas ajouter de nouvelles sous-classes, et :: est final, donc vous ne pouvez pas le sous-classer.

  • Même si vous ne pouvez rien faire pour modifier une liste, elle utilise l'état mutable en interne dans certaines opérations. Cela aide à la performance, mais il est localisé de sorte qu'aucun programme que vous écrivez ne puisse jamais le détecter ou en subir les conséquences. Vous pouvez faire circuler des listes comme vous le souhaitez, peu importe ce que font les autres fonctions ou combien de threads les utilisent simultanément.

Questions connexes