3

セクションがあり、各セクションに多数のレコードがある独自のファイル形式を解析してきました。セクションは任意の順序にすることができ、レコードは任意の順序にすることができます。順序は重要ではありません。セクションを複製するべきではありませんが、それを保証することはできません。

私は parboiled2 を使用して、次のような形式を使用して AST を生成しています。

oneOrMore( Section1 | Section2 | Section3 )

すべてのセクションがケース クラスを生成する場所。それらは何からも継承しません。Seq[Any]

これらのセクション ケース クラスにはSeq[T]、セクション タイプに固有のレコードも含まれています。

Seq[Any]を に変換したい

case class (section1:Seq[T1], section2:Seq[T2], section3:Seq[T3] )

誰かがそのための巧妙で読みやすいテクニックを持っていますか、それとも変更可能なコレクションをいくつか作成し、一致する foreach を使用する必要がありますか?

vars を使用して foreach に戻ると、Scala の魔法が足りないようにいつも感じます。

EDIT 1:共通の基本クラスを拡張する必要があることが提起されました。それは可能です。matchしかし、タイプを識別するためにまだ使用する必要がある場合、ソリューションについて何が変わるのかわかりません。さまざまなケース クラス タイプを分離したいと考えていますBCEFSeq[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()
 }

EDIT 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) )
4

1 に答える 1