2008-09-10 19 views
16

Ich habe kürzlich an einem Anfängerprojekt in Scala gearbeitet und habe eine Anfängerfrage zu Scala's Listen.Ein Element aus einer Liste in Scala zurückgeben

Sagen wir, ich habe eine Liste von Tupeln (List[Tuple2[String, String]], zum Beispiel). Gibt es eine Bequemlichkeitsmethode, um das erste Auftreten eines bestimmten Tupels aus der Liste zurückzugeben, oder ist es notwendig, die Liste manuell zu durchlaufen?

Antwort

6

Sie könnten versuchen mit find. (Aktualisierter scala-doc Ort der Suche)

2

Wenn Sie scala lernen, würde ich mir die Seq Eigenschaft genau ansehen. Es liefert die Grundlage für einen Großteil der funktionalen Güte von scala.

+0

Die Verbindung ist unterbrochen. – ctford

+0

Der Link funktioniert. – akauppi

13
 
scala> val list = List(("A", "B", 1), ("C", "D", 1), ("E", "F", 1), ("C", "D", 2), ("G", "H", 1)) 
list: List[(java.lang.String, java.lang.String, Int)] = List((A,B,1), (C,D,1), (E,F,1), (C,D,2), (G,H,1)) 

scala> list find {e => e._1 == "C" && e._2 == "D"} 
res0: Option[(java.lang.String, java.lang.String, Int)] = Some((C,D,1)) 
+2

Ist es möglich, nicht einige ((C, D, 1)) sondern (C, D, 1) zurückzugeben? Ich meine den gleichen Weg, wenn ich Liste (1) benutzen würde. – grass

+2

@grass Was sollte der Rückgabewert sein, wenn das Tripel '(C, D, 1)' nicht in der Liste gefunden wird? –

+1

Keine oder Ausnahme oder leeres Set. Wäre toll, wenn es eine Möglichkeit gibt, den Rückgabewert anzupassen, wenn das Triple nicht gefunden wird (außer dass ich meine eigene find() -Methode schreibe). – grass

3

Wie in einem früheren Kommentar erwähnt, ist find wahrscheinlich der einfachste Weg, dies zu tun. Es gibt tatsächlich drei verschiedene "lineare Suchmethoden" in Scalas Kollektionen, die jeweils einen etwas anderen Wert ergeben. Welche Sie verwenden, hängt davon ab, wofür Sie die Daten benötigen. Benötigen Sie zum Beispiel einen Index oder benötigen Sie nur einen booleschen true/false?

+0

Können Sie mehr Informationen zu diesen "linearen Suchmethoden" geben? Ich suche nach dem Index eines Tupels (mit nur einem Teil des Tupels) – krookedking

+0

eigentlich habe ich gefunden, was ich gesucht habe: '.zipWithIndex.collect {case (" partOfTuple ", _, i) => i } ' – krookedking

1

Sie auch dies tun könnte, die nicht die Feldnamen in der Tuple2 Klasse erfordert zu wissen - es nutzt Muster statt passend:

list find { case (x,y,_) => x == "C" && y == "D" } 

„finden“ ist gut, wenn Sie wissen, dass Sie nur ein benötigen ; wenn Sie alle passenden Elemente finden möchten können Sie entweder verwenden „Filter“ oder das Äquivalent zuckerhaltig für das Verständnis:

for ((x,y,z) <- list if x == "C" && y == "D") yield (x,y,z) 
+1

Ihr zweites Beispiel scheint viel mehr wie' filter' zu funktionieren, dh es werden * alle * Elemente zurückgegeben, die zu der Eigenschaft passen, nicht die einzige erste als Frage, die der Autor will. –

1

Hier ist Code, der Ihnen helfen kann.

Ich hatte einen ähnlichen Fall, eine Sammlung von Basisklasse Einträgen (hier A) aus dem ich eine bestimmten abgeleitete Klasse des Knotens, falls vorhanden (hier B) finden wollte.

class A 

case class B(val name: String) extends A 

object TestX extends App { 
    val states: List[A] = List(B("aa"), new A, B("ccc")) 

    def findByName(name: String): Option[B] = { 
    states.find{ 
     case x: B if x.name == name => return Some(x) 
     case _ => false 
    } 
    None 
    } 

    println(findByName("ccc")) // "Some(B(ccc))" 
} 

Der wichtige Teil hier (für meine app) ist, dass findByName nicht Option[A] aber Option[B] zurückgibt.

Sie können das Verhalten einfach so ändern, dass B zurückgegeben wird, und eine Ausnahme auslösen, wenn keine gefunden wurde. Hoffe das hilft.

1

Betrachten collectFirst die Some[(String,String)] für die erste passende Tupel oder None anderweitig, zum Beispiel liefert, wie folgt

xs collectFirst { case [email protected](a,_) if a == "existing" => t } 
Some((existing,str)) 

scala> xs collectFirst { case [email protected](a,_) if a == "nonExisting" => t } 
None 

Mit @ wir den Wert des Tupels zu t binden, so dass ein ganzen Anpassungs Tupel gesammelt werden kann .