2010-09-03 3 views
5

zum Beispiel aus einer folgenden Datei:In Scala, wie ein Element in CSV durch ein Paar Schlüsselwerte zu finden?

 
Name,Surname,E-mail 
John,Smith,[email protected] 
Nancy,Smith,[email protected] 
Jane,Doe,[email protected] 
John,Doe,[email protected] 

wie bekomme ich E-Mail-Adresse des John Doe?

Ich verwende den folgenden Code jetzt, aber jetzt nur ein Schlüsselfeld angeben:

 

val src = Source.fromFile(file) 
val iter = src.getLines().drop(1).map(_.split(",")) 
var quote = "" 
iter.find(_(1) == "Doe" ) foreach (a => println(a(2))) 
src.close() 
 

ich mit dem Schreiben habe versucht, „iter.find (_ (0) == "John" & & _ (1) == "Doe") ", aber dies wirft einen Fehler auf, der besagt, dass nur ein Parameter erwartet wird (das Einschließen der Bedingung in ein zusätzliches Paar von Klammern hilft nicht).

+0

Wenn dies wirklich eine CSV-Datei ist, ist die Verwendung von StringOps.split (",") fehlerhaft und behandelt nicht die Fälle, in denen ein Komma (,) und/oder ein Doppelzitat (") Teil eines embedded value. Ich habe das gerade in meiner StackOverflow-Antwort hier angesprochen: http://stackoverflow.com/a/32488453/501113 – chaotic3quilibrium

Antwort

5

Der Unterstrich als Platzhalter für einen Parameter zu einem Lambda funktioniert nicht so, wie Sie denken.

a => println(a) 
// is equivalent to 
println(_) 

(a,b) => a + b 
// is equivalent to 
_ + _ 

a => a + a 
// is not equivalent to 
_ + _ 

Das bedeutet, daß der erste Unterstreichungs den ersten Parameter und das zweite Mittel den zweiten Parameter und so weiter. Das ist also der Grund für den Fehler, den Sie sehen - Sie verwenden zwei Unterstriche, haben aber nur einen Parameter. Die Lösung ist die explizite Version zu verwenden:

iter.find(a=> a(0) == "John" && a(1) == "Doe") 
1

Sie Regex verwenden können:

scala> def getRegex(v1: String, v2: String) = (v1 + "," + v2 +",(\\S+)").r 
getRegex: (v1: String,v2: String)scala.util.matching.Regex 

scala> val src = """John,Smith,[email protected] 
    | Nancy,Smith,[email protected] 
    | Jane,Doe,[email protected] 
    | John,Doe,[email protected] 
    | """ 
src: java.lang.String = 
John,Smith,[email protected] 
Nancy,Smith,[email protected] 
Jane,Doe,[email protected] 
John,Doe,[email protected] 


scala> val MAIL = getRegex("John","Doe") 
MAIL: scala.util.matching.Regex = John,Doe,(\S+) 

scala> val itr = src.lines 
itr: Iterator[String] = non-empty iterator 

scala> for(MAIL(address) <- itr) println(address) 
[email protected] 

scala> 
+1

Und Sie können auch MAIL.findAllIn (src). – Eastsun

0

Sie auch ein Mustervergleich auf dem Ergebnis der split in einem for Verständnis tun könnte.

val firstName = "John" 
val surName = "Doe" 
val emails = for { 
    Array(`firstName`, `surName`, email) <- 
    src.getLines().drop(1) map { _ split ',' } 
} yield { email } 

println(emails.mkString(",")) 

Beachten Sie die Backticks in dem Muster: dies bedeutet, dass wir auf dem Wert von firstName passen, anstatt eine neue variable Anpassungs etwas einzuführen und die val firstname Shadowing.

+0

Verwenden von StringOps.split (",") ist fehlerhaft und behandelt nicht die Fälle, in denen entweder ein Komma (,) und/oder ein Doppelzitat (") Teil eines eingebetteten Wertes ist. Ich habe dies in meiner StackOverflow-Antwort hier angesprochen: stackoverflow.com/a/32488453/501113 – chaotic3quilibrium

Verwandte Themen