解析 CSV 并仅将匹配的行添加到 Scala 中的功能列表

Parse CSV and add only matching rows to List functionally in Scala

我正在阅读 csv scala。 人是个案class

Case class Person(name, address)

    def getData(path:String,existingName) : List[Person] = {

      Source.fromFile(“my_file_path”).getLines.drop(1).map(l => {
        val data = l.split("|", -1).map(_.trim).toList
        val personName  = data(0)

        if(personName.equalsIgnoreCase(existingName)) {
          val address=data(1)
          Person(personName,address)
           //here I want to add to list

        }
        else
          Nil
       ///here return empty list of zero length


     }).toList()

}

我想在 Scala 中实现这个功能。

这是我认为您正在尝试做的事情的基本方法。

case class Person(name:String, address:String)

def getData(path:String, existingName:String) :List[Person] = {
  val recordPattern = raw"\s*(?i)($existingName)\s*\|\s*(.*)".r.unanchored

  io.Source.fromFile(path).getLines.drop(1).collect {
    case recordPattern(name,addr) => Person(name, addr.trim)
  }.toList
}

这不会关闭文件 reader 或在文件无法打开时报告错误,您确实应该这样做,但我们将在另一天讨论。


更新:通过Using (Scala 2.13)

添加文件关闭和错误处理
import scala.util.{Using, Try}

case class Person(name:String, address:String)

def getData(path:String, existingName:String) :Try[List[Person]] =
  Using(io.Source.fromFile(path)){ file =>
    val recordPattern = raw"\s*(?i)($existingName)\s*\|\s*([^|]*)".r

    file.getLines.drop(1).collect {
      case recordPattern(name,addr) => Person(name, addr.trim)
    }.toList
  }

更新更新

好的。这是一个版本:

  • 文件打不开报错
  • 打开并读取后关闭文件
  • 忽略不需要的空格和引号
  • 2.13 之前的编译器友好
import scala.util.Try

case class Person(name:String, address:String)

def getData(path:String, existingName:String) :List[Person] = {
  val recordPattern =
    raw"""[\s"]*(?i)($existingName)["\s]*\|[\s"]*([^"|]*)*.""".r

  val file = Try(io.Source.fromFile(path))
  val res = file.fold(
    err => {println(err); List.empty[Person]},
    _.getLines.drop(1).collect {
      case recordPattern(name,addr) => Person(name, addr.trim)
    }.toList)
  file.map(_.close)
  res
}

正则表达式的工作原理如下:

  • [\s"]* 可能有空格或引号
  • (?i)匹配不区分大小写
  • ($existingName) 匹配并捕获此字符串(第一个捕获组)
  • ["\s]* 可能有空格或引号
  • \|会有一个横条字符
  • [\s"]* 可能有空格或引号
  • ([^"|]*) 匹配并捕获除 quote 或 bar
  • 之外的所有内容
  • .* 忽略之后可能发生的任何事情

你不是很清楚你的方法有什么问题,但这应该可以解决问题(非常接近你所拥有的)

 def getData(path:String, existingName: String) : List[Person] = {

    val source = Source.fromFile("my_file_path")
    val lst = source.getLines.drop(1).flatMap(l => {
      val data = l.split("|", -1).map(_.trim).toList
      val personName = data.head

      if (personName.equalsIgnoreCase(existingName)) {
        val address = data(1)
        Option(Person(personName, address))
      }
      else
        Option.empty
    }).toList

    source.close()

    lst
  }

我们每行读取文件行,对于每一行,我们从第一个 csv 字段中提取 personName,如果它是我们正在寻找的人,我们 return 一个(选项)人,否则 none(Option.empty)。通过 flatmap 我们丢弃空选项(只是为了避免使用 nils)