Obtenir un élément dans la liste dans Scala?


205

Comment dans le monde obtenez-vous juste un élément à l'index i de la liste en scala?

J'ai essayé get(i), et [i] - rien ne fonctionne. La recherche sur Google indique uniquement comment "trouver" un élément dans la liste. Mais je connais déjà l'index de l'élément!

Voici le code qui ne compile pas:

def buildTree(data: List[Data2D]):Node ={
  if(data.length == 1){
      var point:Data2D = data[0]  //Nope - does not work

  }
  return null
}

Regarder l' API List n'aide pas, car mes yeux se croisent.


1
Eh bien, il semble que data.head ait fonctionné ... Mais cela ne me donne tout de même que le premier élément, personne dans la liste.
Andriy Drozdyuk

Utilisez les traits Seq s'appliquent (index) si vous êtes sûr que l'indice n'est pas hors limites. scala-lang.org/api/current/…
Beezer

data.drop (i) .head fonctionne pour accéder au i-ème élément
Vinay

@Vinay C'est une opération coûteuse. Il faut donc éviter "drop (i) .head".
Shubham Agrawal

Réponses:


306

Utilisez des parenthèses:

data(2)

Mais vous ne voulez pas vraiment le faire très souvent avec des listes, car les listes liées prennent du temps à parcourir. Si vous souhaitez indexer dans une collection, utilisez Vector(immuable) ou ArrayBuffer(mutable) ou éventuellement Array(qui est juste un tableau Java, sauf que vous l'indexez avec (i)au lieu de [i]).


1
Fondamentalement, je recherche quelque chose comme ArrayList en java. Je suppose que l'immuable serait bien aussi.
Andriy Drozdyuk

1
ArrayBufferfonctionne comme ArrayList. Vectorfonctionne comme un immuable - ArrayListvous pouvez lire, mais vous ne pouvez pas écrire sans en créer un nouveau.
Rex Kerr

Que diriez-vous d'une sous-liste? Par exemple, en Java, je fais "data.subList (0, index)".
Andriy Drozdyuk

Peu importe, je l'ai - c'est "tranche"! Puis-je convertir ArrayBuffer en vecteur? Ou existe-t-il un type plus générique que je peux renvoyer des méthodes? Par exemple, en Java, je retournerais l'interface List.
Andriy Drozdyuk

1
Vous pouvez convertir ArrayBufferen une IndexedSequtilisation .toIndexedSeq; IndexedSeqest le type le plus générique. (Dans ce cas, il s'avère être implémenté comme un Vector.) IndexedSeqEst le super-type de collections qu'il est raisonnable d'indexer. Notez également que vous pouvez le faire Vector() ++ myArrayBuffer, ce qui fonctionnera pour presque toutes les collections (de chaque côté). ++crée une nouvelle collection à partir des deux que vous spécifiez, en conservant le type de celle de gauche. Vector()est le vecteur vide, il produira donc ce que vous voulez.
Rex Kerr

121

Plus sûr est d'utiliser liftafin que vous puissiez extraire la valeur si elle existe et échouer gracieusement dans le cas contraire.

data.lift(2)

Cela retournera None si la liste n'est pas assez longue pour fournir cet élément, et Some (valeur) s'il l'est.

scala> val l = List("a", "b", "c")
scala> l.lift(1)
Some("b")
scala> l.lift(5)
None

Chaque fois que vous effectuez une opération qui peut échouer de cette façon, il est bon d'utiliser une option et d'obtenir le système de type pour vous assurer que vous gérez le cas où l'élément n'existe pas.

Explication:

Cela fonctionne parce que List apply(qui propose des parenthèses, par exemple l(index)) est comme une fonction partielle qui est définie partout où la liste a un élément. La List.liftméthode transforme la applyfonction partielle (une fonction qui n'est définie que pour certaines entrées) en une fonction normale (définie pour n'importe quelle entrée) en enveloppant essentiellement le résultat dans une option.


11
L'ascenseur est beau. Je peux éviter les erreurs arrayIndexOutOfBound, sans vérifier la taille du tableau ..
Naveen Sachar

9

Pourquoi des parenthèses?

Voici la citation de la programmation du livre en scala .

Une autre idée importante illustrée par cet exemple vous donnera un aperçu de la raison pour laquelle les tableaux sont accessibles avec des parenthèses dans Scala. Scala a moins de cas spéciaux que Java. Les tableaux sont simplement des instances de classes comme toute autre classe dans Scala. Lorsque vous appliquez des parenthèses entourant une ou plusieurs valeurs à une variable, Scala transforme le code en invocation d'une méthode nommée apply sur cette variable. Donc ,reetStrings (i) se transforme en greetStrings.apply (i). Ainsi, accéder à un élément d'un tableau dans Scala est simplement un appel de méthode comme les autres. Ce principe n'est pas limité aux tableaux: toute application d'un objet à certains arguments entre parenthèses sera transformée en appel de méthode apply. Bien sûr, cela ne se compilera que si ce type d'objet définit réellement une méthode apply. Ce n'est donc pas un cas spécial; c'est une règle générale.

Voici quelques exemples comment extraire certains éléments (premier élément dans ce cas) en utilisant un style de programmation fonctionnel.

  // Create a multdimension Array 
  scala> val a = Array.ofDim[String](2, 3)
  a: Array[Array[String]] = Array(Array(null, null, null), Array(null, null, null))
  scala> a(0) = Array("1","2","3")
  scala> a(1) = Array("4", "5", "6")
  scala> a
  Array[Array[String]] = Array(Array(1, 2, 3), Array(4, 5, 6))

  // 1. paratheses
  scala> a.map(_(0))
  Array[String] = Array(1, 4)
  // 2. apply
  scala> a.map(_.apply(0))
  Array[String] = Array(1, 4)
  // 3. function literal
  scala> a.map(a => a(0))
  Array[String] = Array(1, 4)
  // 4. lift
  scala> a.map(_.lift(0))
  Array[Option[String]] = Array(Some(1), Some(4))
  // 5. head or last 
  scala> a.map(_.head)
  Array[String] = Array(1, 4)


-1

C'est le moyen préféré pour accéder aux données d'une liste via un index de nos jours:

scala> val list = List("a","b","c")
scala> list.get(1)
Some("b")
scala> list.get(5)
None

Mais comme Rex Kerr mentionné ci-dessus: Si vous utilisez des index, vous devriez envisager d'utiliser Vector au lieu d'une liste.


value get n'est pas membre de List [String]
Greenev
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.