我一直在解析一个有部分的专有文件格式,每个部分都有很多记录。各节可以按任何顺序排列,也可以按任何顺序记录。这个命令并不重要。虽然章节不应该重复,但我不能保证。
我一直使用parboiled2来使用如下格式生成AST:
oneOrMore( Section1 | Section2 | Section3 )每个部分都生成一个案例类。他们不会继承任何导致Seq[Any]的东西
这些区段案例类还包含特定于节类型的记录的Seq[T]。
我想将Seq[Any]转换为
case class (section1:Seq[T1], section2:Seq[T2], section3:Seq[T3] )有人有一个聪明和容易阅读的技术,或我是否应该做一些可变的集合,并使用一个匹配?
当我回到vars的前哨时,我总是觉得自己错过了Scala的魔力。
编辑1:有人提出我应该扩展一个公共基类,我确实可以。但是,如果我仍然必须使用match来识别类型,我看不出解决方案会发生什么变化。我想分离出不同的案例类类型,例如,下面我想将所有的B、C、E和F合并成一个Seq[B]、Seq[C]、Seq[E]和Seq[F]。
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:折叠解决方案
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:可译性
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) )发布于 2016-05-04 23:09:50
虽然可以使用无形状的方法来创建更简洁的解决方案(如Travis pointed out),但我选择了一个基于Travis反馈的纯Scala解决方案。
下面是一个使用foldLeft操作元组外壳强类型Seq[]的示例。不幸的是,每一种可能的类型都需要在比赛中有一个案例,如果有很多类型的话,这种情况可能会变得很乏味。
还要注意的是,如果基类是密封的,那么匹配将在类型丢失时发出详尽的警告,从而保证此操作类型的安全性。
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) )https://stackoverflow.com/questions/35875199
复制相似问题