ケースクラスをタプルに変換する簡単な方法はありますか?
もちろん、これを行うためのボイラープレートコードを簡単に作成できますが、ボイラープレートがなくてもかまいません。
私が実際に求めているのは、ケースクラスを辞書式順序で簡単に作成する方法です。 scala.math.Ordering.Implicits._とvoilaをインポートすることでタプルの目標を達成でき、タプルにはOrderingが定義されています。しかし、scala.math.Orderingのインプリシットは、ケースクラスでは一般的に機能しません。
コンパニオンオブジェクトでunapply().get
を呼び出すのはどうですか?
case class Foo(foo: String, bar: Int)
val (str, in) = Foo.unapply(Foo("test", 123)).get
// str: String = test
// in: Int = 123
Shapeless がこれを行います。
import shapeless._
import shapeless.syntax.std.product._
case class Fnord(a: Int, b: String)
List(Fnord(1, "z - last"), Fnord(1, "a - first")).sortBy(_.productElements.tupled)
取得
res0: List[Fnord] = List(Fnord(1,a - first), Fnord(1,z - last))
productElementsは、ケースクラスをShapeless HListに変換します。
scala> Fnord(1, "z - last").productElements
res1: Int :: String :: shapeless.HNil = 1 :: z - last :: HNil
そしてHListは#tupledでタプルに変換されます:
scala> Fnord(1, "z - last").productElements.tupled
res2: (Int, String) = (1,z - last)
常にコンバージョンを達成しているため、パフォーマンスは恐ろしいものになる可能性があります。おそらく、すべてをタプル形式に変換し、それを並べ替えてから、(Fnord.apply _).tupled
のようなものを使用して変換します。
ProductN
が拡張するN = 1-22の場合、TupleN
特性を拡張してみてください。 _1
、_2
などのメソッドのような多くのタプルセマンティクスを提供します。タイプの使用方法によっては、実際のタプルを作成しなくても十分な場合があります。
同じことをやろうとしているときに、この古いスレッドに出くわしました。私は最終的にこの解決策に落ち着きました:
case class Foo(foo: String, bar: Int)
val testFoo = Foo("a string", 1)
val (str, in) = testFoo match { case Foo(f, b) => (f, b) }