开发者

In Scala, how to find an elemein in CSV by a pair of key values?

开发者 https://www.devze.com 2023-01-14 01:38 出处:网络
For example, from a following file: Name,Surname,E-mail John,Smith,john.smith@hotmail.com Nancy,Smith,nancy.smith@gmail.com

For example, from a following file:

Name,Surname,E-mail
John,Smith,john.smith@hotmail.com
Nancy,Smith,nancy.smith@gmail.com
Jane,Doe,jane.doe@aol.com
John,Doe,john.doe@yahoo.com

how do I get e-mail address of John Doe?

I use the following code now, but can specify only one key field now:


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开发者_JAVA百科.close()

I've tried writing "iter.find( _(0) == "John" && _(1) == "Doe" )", but this raises an error saying that only one parameter is expected (enclosing the condition into extra pair of parentheses does not help).


The underscore as a placeholder for a parameter to a lambda doesn't work the way that you think.

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

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

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

That is, the first underscore means the first parameter and the second one means the second parameter and so on. So that's the reason for the error that you're seeing -- you're using two underscores but have only one parameter. The fix is to use the explicit version:

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


You can use Regex:

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,john.smith@hotmail.com
     | Nancy,Smith,nancy.smith@gmail.com
     | Jane,Doe,jane.doe@aol.com
     | John,Doe,john.doe@yahoo.com
     | """
src: java.lang.String =
John,Smith,john.smith@hotmail.com
Nancy,Smith,nancy.smith@gmail.com
Jane,Doe,jane.doe@aol.com
John,Doe,john.doe@yahoo.com


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)
john.doe@yahoo.com

scala>


You could also do a pattern match on the result of split in a for comprehension.

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

println(emails.mkString(","))

Note the backticks in the pattern: this means we match on the value of firstName instead of introducing a new variable matching anything and shadowing the val firstname.

0

精彩评论

暂无评论...
验证码 换一张
取 消