Artikel in die Liste in Scala aufnehmen?


205

Wie um alles in der Welt erhalten Sie nur ein Element bei Index i aus der Liste in Scala?

Ich habe es versucht get(i)und [i]- nichts funktioniert. Googeln gibt nur zurück, wie ein Element in der Liste "gefunden" wird. Aber ich kenne schon den Index des Elements!

Hier ist der Code, der nicht kompiliert wird:

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

  }
  return null
}

Ein Blick auf die Listen-API hilft nicht, da sich meine Augen nur kreuzen.


1
Nun gut, es scheint, als hätte data.head funktioniert ... Aber das gibt mir immer noch nur das erste Element, keines in der Liste.
Andriy Drozdyuk

Verwenden Sie die Seq- Merkmale anwenden (Index), wenn Sie sicher sind, dass der Index nicht außerhalb der Grenzen liegt. scala-lang.org/api/current/…
Beezer

data.drop (i) .head funktioniert für den Zugriff auf das i-te Element
Vinay

@ Vinay Das ist eine kostspielige Operation. Man sollte also "drop (i) .head" vermeiden.
Shubham Agrawal

Antworten:


305

Verwenden Sie Klammern:

data(2)

Aber Sie möchten das nicht wirklich oft mit Listen tun, da das Durchlaufen verknüpfter Listen einige Zeit in Anspruch nimmt. Wenn Sie in eine Sammlung indizieren möchten, verwenden Sie Vector(unveränderlich) oder ArrayBuffer(veränderlich) oder möglicherweise Array(dies ist nur ein Java-Array, außer Sie indizieren erneut mit (i)statt [i]).


1
Grundsätzlich suche ich so etwas wie ArrayList in Java. Ich denke, unveränderlich wäre auch in Ordnung.
Andriy Drozdyuk

1
ArrayBufferfunktioniert wie ArrayList. Vectorfunktioniert wie ein unveränderlicher - ArrayListSie können lesen, aber Sie können nicht schreiben, ohne einen neuen zu erstellen.
Rex Kerr

Wie wäre es mit einer Unterliste? Zum Beispiel mache ich in Java "data.subList (0, index)".
Andriy Drozdyuk

Egal, ich habe es verstanden - es ist "Scheibe"! Kann ich ArrayBuffer in Vector konvertieren? Oder gibt es einen allgemeineren Typ, den ich von Methoden zurückgeben kann? Zum Beispiel würde ich in Java die List-Schnittstelle zurückgeben.
Andriy Drozdyuk

1
Sie können ArrayBufferin eine IndexedSequsing konvertieren .toIndexedSeq; IndexedSeqist der allgemeinere Typ. (In diesem Fall stellt sich heraus, dass es tatsächlich als. Implementiert ist Vector.) IndexedSeqIst der Supertyp von Sammlungen, in die eine Indizierung sinnvoll ist. Beachten Sie auch, dass Sie dies tun können Vector() ++ myArrayBuffer, was für fast jede Sammlung (auf beiden Seiten) funktioniert. ++Erstellt aus den beiden angegebenen eine neue Sammlung, wobei der Typ der linken beibehalten wird. Vector()ist der leere Vektor, also würde er produzieren, was Sie wollen.
Rex Kerr

121

Sicherer ist die Verwendung, liftdamit Sie den Wert extrahieren können, wenn er vorhanden ist, und ordnungsgemäß fehlschlagen können, wenn dies nicht der Fall ist.

data.lift(2)

Dies gibt None zurück, wenn die Liste nicht lang genug ist, um dieses Element bereitzustellen, und Some (Wert), wenn dies der Fall ist.

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

Wenn Sie eine Operation ausführen, die auf diese Weise fehlschlägt, sollten Sie eine Option verwenden und das Typsystem verwenden, um sicherzustellen, dass Sie den Fall behandeln, in dem das Element nicht vorhanden ist.

Erläuterung:

Dies funktioniert, weil Listen apply(die z. B. nur in Klammern stehen l(index)) wie eine Teilfunktion sind, die überall dort definiert wird, wo die Liste ein Element enthält. Die List.liftMethode wandelt die Teilfunktion apply(eine Funktion, die nur für einige Eingaben definiert ist) in eine normale Funktion (für jede Eingabe definiert) um, indem das Ergebnis im Grunde genommen in eine Option eingeschlossen wird.


11
Aufzug ist schön. Ich kann ArrayIndexOutOfBound-Fehler vermeiden, ohne die Größe des Arrays zu überprüfen.
Naveen Sachar

9

Warum Klammern?

Hier ist das Zitat aus der Buchprogrammierung in Scala .

Eine weitere wichtige Idee, die in diesem Beispiel veranschaulicht wird, gibt Ihnen einen Einblick, warum in Scala auf Arrays mit Klammern zugegriffen wird. Scala hat weniger Sonderfälle als Java. Arrays sind einfach Instanzen von Klassen wie jede andere Klasse in Scala. Wenn Sie einer Variablen Klammern um einen oder mehrere Werte zuweisen, wandelt Scala den Code in einen Aufruf einer Methode mit dem Namen apply für diese Variable um. So wird greetStrings (i) in greetStrings.apply (i) umgewandelt. Der Zugriff auf ein Element eines Arrays in Scala ist daher einfach ein Methodenaufruf wie jeder andere. Dieses Prinzip ist nicht auf Arrays beschränkt: Jede Anwendung eines Objekts auf einige Argumente in Klammern wird in einen Apply-Methodenaufruf umgewandelt. Dies wird natürlich nur kompiliert, wenn dieser Objekttyp tatsächlich eine Apply-Methode definiert. Es ist also kein Sonderfall; Es ist eine allgemeine Regel.

Hier sind einige Beispiele, wie Sie ein bestimmtes Element (in diesem Fall das erste Element) mithilfe eines funktionalen Programmierstils abrufen können.

  // 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)


0

Dies ist heutzutage die bevorzugte Methode, um über einen Index auf Daten einer Liste zuzugreifen:

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

Aber wie Rex Kerr oben ausgeführt hat: Wenn Sie Indizes verwenden, sollten Sie in Betracht ziehen, Vektor anstelle einer Liste zu verwenden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.