在功能上将此String转换为对象列表

时间:2014-01-28 17:24:22

标签: scala csv functional-programming

我有一个这种csv格式的字符串:

//> lines  : String = a1 , 2 , 10
//| a2 , 2 , 5
//| a3 , 8 , 4
//| a4 , 5 , 8
//| a5 , 7 , 5
//| a6 , 6 , 4
//| a8 , 4 , 9

我想将此String转换为对象List,其中String的每一行代表对象List中的新条目。我可以想到如何做到这一点 -

将String分成多行并将每一行拆分为其csv标记。循环遍历每一行,并为每一行创建一个新对象并将其添加到List。但是我试图在功能上考虑这个问题而且我不确定从哪里开始。有什么指示吗?

2 个答案:

答案 0 :(得分:4)

假设您从一个迭代器开始,为每一行生成一个String。如果您是从文件加载,则Source类可以执行此操作;如果您已经开始使用val lines = input.split("\n")

中的所有内容,则可以使用String

这也适用于List,Seq等。Iterator不是先决条件。

所以你映射输入来解析每一行

val lines = input split "\n"
val output = lines map { line => parse(line) }

或(无点式)

val output = lines map parse

您需要的只是parse方法,以及应解析行的类型。案例类别是一个不错的选择:

case class Line(id: String, num1: Int, num2: Int)

所以解析。我将把结果包装在Try中,这样你就可以捕获错误:

def parse(line: String): Try[Line] = Try {
  //split on commas and trim whitespace
  line.split(",").trim match { 
    //String.split produces an Array, so we pattern-match on an Array of 3 elems
    case Array(id,n1,n2) =>
      // if toInt fails it'll throw an Exception to be wrapped in the Try
      Line(id, n1.toInt, n2.toInt)
    case x => throw new RuntimeException("Invalid line: " + x)
  }
}

将所有内容放在一起,最终输出为CC[Try[Line]],其中CClines的集合类型(例如Iterator,Seq等)

然后您可以隔离错误:

val (goodLines, badLines) = output.partition(_.isSuccess)

或者,如果您只想删除中间Try并丢弃错误:

val goodLines: Seq[Line] = output collect { case Success(line) => line }

ALL TOGETHER

case class Line(id: String, num1: Int, num2: Int)

def parse(line: String): Try[Line] = Try {
  line.split(",").trim match { 
    case Array(id,n1,n2) => Line(id, n1.toInt, n2.toInt)
    case x => throw new RuntimeException("Invalid line: " + x)
  }
}

val lines = input split "\n"
val output = lines map parse
val (successes, failures) =  output.partition(_.isSuccess)
val goodLines = successes collect { case Success(line) => line }

答案 1 :(得分:3)

由于未提供样本输出,因此不确定这是否是您想要的确切输出。应该能够从中得到你想要的东西。

scala> val lines: String = """a1,2,10
| a2,2,5
| a3,8,4
| a4,5,8
| a5,7,5
| a6,6,4
| a8,4,9"""
lines: String = 
a1,2,10
a2,2,5
a3,8,4
a4,5,8
a5,7,5
a6,6,4
a8,4,9


scala> case class Line(s: String, s2: String, s3: String)
defined class Line

scala> lines.split("\n").map(line => line.split(",")).map(split => Line(split(0), split(1), split(2)))
res0: Array[Line] = Array(Line(a1,2,10), Line(a2,2,5), Line(a3,8,4), Line(a4,5,8), Line(a5,7,5), Line(a6,6,4), Line(a8,4,9))