В Scala есть простой способ преобразовать класс case в кортеж? - PullRequest
52 голосов
/ 11 ноября 2011

Есть ли простой способ преобразовать класс case в кортеж?

Конечно, я могу легко написать шаблонный код для этого, но я имею в виду без шаблонного.

Что мне действительно нужно, так это способ легко составить лексикографически упорядоченный класс кейсов. Я могу достичь цели для кортежей, импортировав scala.math.Ordering.Implicits._ и вуаля, мои кортежи имеют определенный порядок для них. Но последствия в scala.math.Ordering не работают для case-классов в целом.

Ответы [ 4 ]

73 голосов
/ 11 ноября 2011

Как насчет вызова unapply().get в объекте-компаньоне?

case class Foo(foo: String, bar: Int)

val (str, in) = Foo.unapply(Foo("test", 123)).get
// str: String = test
// in: Int = 123
4 голосов
/ 05 февраля 2018

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 превращает класс кейса в бесформенный HList:

scala> Fnord(1, "z - last").productElements
res1: Int :: String :: shapeless.HNil = 1 :: z - last :: HNil

И списки HL преобразуются в кортежи с #tupled:

scala> Fnord(1, "z - last").productElements.tupled
res2: (Int, String) = (1,z - last)

Производительность может быть ужасной, поскольку вы постоянно конвертируете.Вы, вероятно, конвертируете все в кортежную форму, сортируете ее, а затем конвертируете обратно, используя что-то вроде (Fnord.apply _).tupled.

3 голосов
/ 11 ноября 2011

Вы можете попытаться расширить черту ProductN, для N = 1-22, которая расширяет TupleN.Это даст вам много семантики Tuple, например методы _1, _2 и т. Д.В зависимости от того, как вы используете ваши типы, этого может быть достаточно без создания фактического кортежа.

1 голос
/ 09 апреля 2017

Наткнулся на эту старую ветку, пытаясь сделать то же самое.В конце концов я остановился на этом решении:

case class Foo(foo: String, bar: Int)

val testFoo = Foo("a string", 1)

val (str, in) = testFoo match { case Foo(f, b) => (f, b) }
...