解析 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)
我正在阅读 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)