【问题标题】:In Scala, how to find an elemein in CSV by a pair of key values?在Scala中,如何通过一对键值在CSV中找到一个elemein?
【发布时间】:2010-09-03 02:47:49
【问题描述】:

例如,来自以下文件:

姓名、姓氏、电子邮件 约翰,史密斯,john.smith@hotmail.com 南希,史密斯,nancy.smith@gmail.com Jane,Doe,jane.doe@aol.com John,Doe,john.doe@yahoo.com

我如何获得 John Doe 的电子邮件地址?

我现在使用以下代码,但现在只能指定一个关键字段:

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

我试过写“iter.find( _(0) == "John" && _(1) == "Doe" )",但这会引发一个错误,指出只需要一个参数(包含将条件放入额外的一对括号没有帮助)。

【问题讨论】:

  • 如果这真的是一个 CSV 文件,使用 StringOps.split(",") 是错误的,并且不处理逗号 (,) 和/或双引号 (" ) 是嵌入值的一部分。我刚刚在 StackOverflow 的回答中解决了这个问题:stackoverflow.com/a/32488453/501113

标签: scala file-io csv


【解决方案1】:

下划线作为 lambda 参数的占位符并不像您想象的那样起作用。

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

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

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

即第一个下划线表示第一个参数,第二个下划线表示第二个参数,以此类推。这就是您看到错误的原因——您使用了两个下划线但只有一个参数。解决方法是使用显式版本:

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

【讨论】:

    【解决方案2】:

    您可以使用正则表达式:

    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>
    

    【讨论】:

    • 你也可以使用 MAIL.findAllIn(src)。
    【解决方案3】:

    您还可以在 for 理解中对 split 的结果进行模式匹配。

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

    注意模式中的反引号:这意味着我们匹配 firstName 的值,而不是引入匹配任何内容的新变量并隐藏 val firstname

    【讨论】:

    • 使用 StringOps.split(",") 是错误的,并且不能处理逗号 (,) 和/或双引号 (") 是嵌入值的一部分的情况。我刚刚在我的 StackOverflow 答案中解决了这个问题:stackoverflow.com/a/32488453/501113
    猜你喜欢
    • 2018-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-28
    • 2019-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多