我将阅读的原始数据文件是制表符分隔的,其中一个字段是时间戳:
timestamp userId keyword
1405377264 A google
1405378945 B yahoo
1405377264 C facebook
我有一个案例类定义为:
case class Event(date: String, userId: Int, keyword: String)
如何将时间戳转换为Date格式,然后映射到Event case类?我有将时间戳转换为日期的逻辑:
import java.text.SimpleDateFormat
import java.util.Date
val df = new SimpleDateFormat("yyyy-MM-dd")
val dt = new Date(timestamp*1000L)
val date = df.format(dt)
转换原始数据并将其映射到案例类的正确方法是什么?
谢谢!
答案 0 :(得分:3)
我不知道我是否说这是正确的方式,但是读取每一行的一种方法是使用正则表达式提取。假设您已将数据作为字符串,每个行标签分隔,每行由换行符(\n
)分隔:
val data: String = ...
val regex = "(\\d+)\t([A-z])\t([A-z]+)".r
data.split('\n').map { line =>
val regex(timestamp, userId, keyword) = line
Event(df.format(new Date(timestamp.toLong*1000L), userId, keyword)
}
按原样,如果与正则表达式有任何偏差(这必须根据您的需要进行调整,我只能遵循上面的示例),这不是容错的。例如,如果您想丢弃不符合的行,可以使用Try
和collect
:
data.split('\n').map { line =>
Try {
// same as above
}
}.collect {
case Success(event) => event
}
答案 1 :(得分:2)
如何使用scala.io.Source.fromFile(myFile.csv).getLines读取CSV文件?这应该返回一个Iterator [String],这是一个懒惰的集合!
您可以在每一行上映射以创建一个事件。但你想要的是在创建Event对象之前将时间戳转换为java.util.Date作为第一步。
我会在这些方面提出一些建议:(这可能无法编译,但它应该给你基本的想法)
scala.io.Source.fromFile(myFile.csv).getLines flatMap { line =>
splitAtDelimiter(line).toList match {
case ts :: id :: kw :: Nil =>
val date: Option[String] =
try { Some(convertToDateString(ts)) } catch { case e: Throwable => None }
date.map(Event(_, getUserIdColumn(line), getKeyWordColumn(line)) // returns an Option[Event]
case _ => None
}
你的convertToDateString
是一个函数,它接受时间戳值并将其转换为java.util.Date,然后在其上执行toString(查看事件案例类中日期类型所需的内容) )splitAtDelimiter
是一个虚构的CSV解析器函数!