在Scala中有一种很好的方法来解释CSV中的值类型

时间:2014-03-09 03:11:08

标签: scala parsing csv types

假设我获得了一个包含以下值的CSV:

0, 1.00, Hello
3, 2.13, World
  .
  .
  .

是否有一个好的方法或库可以自动检测最佳类型以将给定列分类为?在这种情况下(Int,Float,String)。

对于更多上下文,我正在尝试扩展CSV解析库,以允许它报告传递的CSV上的数据直方图。这个想法是让很容易将某些验证任务添加到此框架中至于弄清楚CSV数据转储中的缺陷或不规范。

最初我想写一些用户可以提供指定类型的配置文件的东西,但是对于CSV列设置非常大的情况,或者只是为了易于使用,我想尝试自动检测类型而不是让用户必须写出来。

2 个答案:

答案 0 :(得分:1)

答案可能是:

def parse(s:String): Any = Try(s.toInt) orElse(Try(s.toDouble)) getOrElse(s)

然后你可以使用模式匹配来随心所欲地做任何事情。

当然,您可以首先对字符串进行常规表达式测试,以查看您拥有的类型。但我相当肯定只是强制执行每种格式的解析,如上所述,会更快。

答案 1 :(得分:0)

考虑解析器组合器;推断类型通过案例类列表进行报告,

import scala.util.parsing.combinator._

trait CSVType
case class LiteralStr extends CSVType
case class Float extends CSVType
case class Integer extends CSVType
case class Bool extends CSVType
case class NA extends CSVType  // Not Available

class CSV extends JavaTokenParsers {   

  def row: Parser[List[CSVType]] = repsep(value, ",")

  def value: Parser[CSVType] =     
    floatingPointNumber ^^ { f => if (f.toDouble.toInt == f.toDouble) Integer() 
                                  else Float() } | 
    "NA"                ^^ { na => NA() } | 
    ("true" | "false")  ^^ { b => Bool() } |
    stringLiteral       ^^ { s => LiteralStr() } 


}


object ParseExpr extends CSV with App {
  println("in: "+ args(0))
  println(parseAll(row, args(0)))
}

因此

scala> val s  = """1.23,2,true,NA,"hello" """
s: String = "1.23,2,true,NA,"hello" "

scala> ParseExpr.main(Array(s))
in: 1.23,2,true,NA,"hello" 
[1.24] parsed: List(Float(), Integer(), Bool(), NA(), LiteralStr())

请注意,组合器包括类型的解析,例如数字,布尔值和字符串。此外,自定义类型由解析器定义,例如NA。有关此处使用的定义,请参阅JavaTokenParsers trait

每个案例类都可能包含额外的逻辑,以便以最方便的方式报告输入。