【问题标题】:scala - equivalent case class for the text parsing that has dynamic number of fieldsscala - 具有动态字段数的文本解析的等效案例类
【发布时间】:2018-11-29 04:23:44
【问题描述】:

我从一个进程接收到一条消息,我正在尝试将它映射到一个案例类。该消息位于用逗号分隔的管道符号中,如下所示

|id1,5,2010-06-19,27.40,2010-06-20,35.40,2010-06-21,8.50,2010-06-22,23.40,2010-06-23,57.40,TX5|

消息是这样打包的

1.id

2.number of occurrences of 3 and 4 together

3.date //it repeats along with 4 based on 2

4.amount //it repeats along with 3 based on 2

5.code -- last field

虽然高层有5个字段,但3和4可以在2的基础上重复。

为了更好地理解,这里有更多示例

|id2,7,2010-06-19,56.40,2010-06-20,23.76,2010-06-21,12.50,2010-06-22,87.12,2010-06-23,52.90,2010-06-24,35.70,2010-06-25,72.80,TX3|
|id3,4,2010-06-19,87.40,2010-06-20,32.40,2010-06-21,21.50,2010-06-22,73.40,TX2|
|id4,6,2010-06-19,56.12,2010-06-20,66.43,2010-06-21,23.12,2010-06-22,87.12,2010-06-23,34.90,2010-06-24,55.00,FT3|

我能够从开头和结尾删除管道符号。解析并获取第一个和最后一个字段。

scala> val str="id1,5,2010-06-19,27.40,2010-06-20,35.40,2010-06-21,8.50,2010-06-22,23.40,2010-06-23,57.40,TX5"
str: String = id1,5,2010-06-19,27.40,2010-06-20,35.40,2010-06-21,8.50,2010-06-22,23.40,2010-06-23,57.40,TX5

scala> val (id,code) = (str.split(",")(0), str.split(",").last)
id: String = id1
code: String = TX5

scala>

但是我如何将其余部分映射到一个案例类中呢?

请注意,这与Scala: Parsing Array of String to a case class 不同,Scala: Parsing Array of String to a case class 的消息具有固定的列数,并且可以轻松映射到案例类

【问题讨论】:

标签: scala


【解决方案1】:

您尚未指定案例类的外观。这是一种可以合理容忍任何格式不佳的输入数据字符串的方法。

case class CC(id        :String
             ,datePrice :Seq[(String,Double)]
             ,code      :String)

import util.Try
def mkCC(dataStr :String) :CC = {
  val dataArr = dataStr.split(",")
  val id      = dataArr.head.filter('|'.!=)
  val code    = dataArr.last.filter('|'.!=)
  val dps     = Try{
    val len = dataArr(1).toInt
    Seq.range(2, len*2+2, 2)
       .flatMap(idx => Try{(dataArr(idx),dataArr(idx+1).toDouble)}.toOption)
  }.getOrElse(Seq())
  CC(id, dps, code)
}

用法:

val data1="|id2,7,2010-06-19,56.40,2010-06-20,23.76,2010-06-21,12.50,2010-06-22,87.12,2010-06-23,52.90,2010-06-24,35.70,2010-06-25,72.80,TX3|"
val data2="|id3,4,2010-06-19,87.40,2010-06-20,32.40,2010-06-21,21.50,2010-06-22,73.40,TX2|"
val data3="|id4,6,2010-06-19,56.12,2010-06-20,66.43,2010-06-21,23.12,2010-06-22,87.12,2010-06-23,34.90,2010-06-24,55.00,FT3|"

val cc1 :CC = mkCC(data1)
val cc2 :CC = mkCC(data2)
val cc3 :CC = mkCC(data3)

【讨论】:

  • 太棒了..这解决了解析...但是可以将 datePrice 转换为一种 JSON 数组吗?...因为我应该能够使用 CC 之类的东西 datePrice.date[ 0] 或 datePrice.Price[1]..not with ._1, ._2...
  • 您可以创建一个单独的类来代替元组DatePrice(date:String, price:Double)。访问权限可能类似于cc3.pds(4).datecc9.pds(0).price。或者您可以选择加载两个单独的数组。访问权限类似于 cc2.date(5)cc1.price(6)。无论哪种方式,解析/加载代码都不会与呈现的编码示例有太大不同。
猜你喜欢
  • 2022-01-27
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 2017-04-22
  • 2011-09-15
  • 1970-01-01
  • 1970-01-01
  • 2018-01-19
相关资源
最近更新 更多