2010-09-03 9 views
5

Por ejemplo, a partir de un archivo siguientes:En Scala, ¿cómo encontrar un elemein en CSV mediante un par de valores clave?

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

cómo consigo dirección de correo electrónico de John Doe?

uso el siguiente código ahora, pero puede especificar sólo un campo clave ahora:

 

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

He intentado escribir "iter.find (_ (0) == "John" & & _ (1) == "Doe") ", pero esto genera un error al decir que solo se espera un parámetro (encerrar la condición en un par adicional de paréntesis no ayuda).

+0

Si esto es realmente un archivo CSV, utilizando StringOps.split (", ') es errónea y no se ocupa de los casos en los que una coma (,) y/o una comilla doble (') son parte de una . embedded value acabo dirigí en mi respuesta StackOverflow aquí:. http://stackoverflow.com/a/32488453/501113 – chaotic3quilibrium

Respuesta

5

El subrayado como un marcador de posición para un parámetro a un lambda no funciona de la manera que usted piensa.

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

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

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

Es decir, el primero de subrayado significa que el primer parámetro y el segundo significa que el segundo parámetro y así sucesivamente. Esa es la razón del error que está viendo: está utilizando dos guiones bajos pero tiene solo un parámetro. La solución es utilizar la versión explícita:

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

Puede utilizar expresiones regulares:

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

Y también se puede utilizar MAIL.findAllIn (src) – Eastsun

0

También puede hacer una comparación de patrones en el resultado de split en una comprensión for.

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

println(emails.mkString(",")) 

Tenga en cuenta los acentos abiertos en el patrón: esto significa que el partido en el valor de firstName en lugar de introducir un nuevo juego algo variable y que cubrían el val firstname.

+0

Usando StringOps.split ("") es erróneo y no trata los casos donde una coma (,) y/o una comilla doble (") son parte de un valor incrustado. Acabo de abordar esto en mi respuesta de StackOverflow aquí: stackoverflow.com/a/32488453/501113 – chaotic3quilibrium

Cuestiones relacionadas