首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将Seq[Any]分解为case类的巧妙方法

将Seq[Any]分解为case类的巧妙方法
EN

Stack Overflow用户
提问于 2016-03-08 18:30:43
回答 1查看 819关注 0票数 3

我一直在解析一个有部分的专有文件格式,每个部分都有很多记录。各节可以按任何顺序排列,也可以按任何顺序记录。这个命令并不重要。虽然章节不应该重复,但我不能保证。

我一直使用parboiled2来使用如下格式生成AST:

代码语言:javascript
复制
oneOrMore( Section1 | Section2 | Section3 )

每个部分都生成一个案例类。他们不会继承任何导致Seq[Any]的东西

这些区段案例类还包含特定于节类型的记录的Seq[T]

我想将Seq[Any]转换为

代码语言:javascript
复制
case class (section1:Seq[T1], section2:Seq[T2], section3:Seq[T3] )

有人有一个聪明和容易阅读的技术,或我是否应该做一些可变的集合,并使用一个匹配?

当我回到vars的前哨时,我总是觉得自己错过了Scala的魔力。

编辑1:有人提出我应该扩展一个公共基类,我确实可以。但是,如果我仍然必须使用match来识别类型,我看不出解决方案会发生什么变化。我想分离出不同的案例类类型,例如,下面我想将所有的BCEF合并成一个Seq[B]Seq[C]Seq[E]Seq[F]

代码语言:javascript
复制
 class A()
 case class B(v:Int) extends A
 case class C(v:String) extends A

 case class E(v:Int)
 case class F(v:String)

 val a:Seq[A] = B(1) :: C("2") :: Nil
 val d:Seq[Any] = E(3) :: F("4") :: Nil

 a.head match {
   case B(v) => v should equal (1)
   case _ => fail()
 }

 a.last match {
   case C(v) => v should equal ("2")
   case _ => fail()
 }

 d.head match {
   case E(v) => v should equal (3)
   case _ => fail()
 }

 d.last match {
   case F(v) => v should equal ("4")
   case _ => fail()
 }

编辑2:折叠解决方案

代码语言:javascript
复制
  case class E(v:Int)
  case class F(v:String)


  val d:Seq[Any] = E(3) :: F("4") :: Nil

  val Ts = d.foldLeft((Seq[E](), Seq[F]()))(
    (c,r) => r match {
      case e:E => c.copy(_1=c._1 :+ e)
      case e:F => c.copy(_2=c._2 :+ e)
    }
  )

  Ts should equal ( (E(3) :: Nil,  F("4") :: Nil) )

编辑3:可译性

代码语言:javascript
复制
  sealed trait A //sealed is important
  case class E(v:Int) extends A
  case class F(v:String) extends A


  val d:Seq[Any] = E(3) :: F("4") :: Nil

  val Ts = d.foldLeft((Seq[E](), Seq[F]()))(
    (c,r) => r match {
      case e:E => c.copy(_1=c._1 :+ e)
      case e:F => c.copy(_2=c._2 :+ e)
    }
  )

  Ts should equal ( (E(3) :: Nil,  F("4") :: Nil) )
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-05-04 23:09:50

虽然可以使用无形状的方法来创建更简洁的解决方案(如Travis pointed out),但我选择了一个基于Travis反馈的纯Scala解决方案。

下面是一个使用foldLeft操作元组外壳强类型Seq[]的示例。不幸的是,每一种可能的类型都需要在比赛中有一个案例,如果有很多类型的话,这种情况可能会变得很乏味。

还要注意的是,如果基类是密封的,那么匹配将在类型丢失时发出详尽的警告,从而保证此操作类型的安全性。

代码语言:javascript
复制
  sealed trait A //sealed is important
  case class E(v:Int) extends A
  case class F(v:String) extends A


  val d:Seq[A] = E(3) :: F("4") :: Nil

  val Ts = d.foldLeft((Seq[E](), Seq[F]()))(
    (c,r) => r match {
      case e:E => c.copy(_1=c._1 :+ e)
      case e:F => c.copy(_2=c._2 :+ e)
    }
  )

  Ts should equal ( (E(3) :: Nil,  F("4") :: Nil) )
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35875199

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档