有没有办法从列表中创建元组(没有代码生成)?

yur*_*ura 15 scala tuples iterable-unpacking

有时需要从小集合中创建元组(例如,烫伤框架).

def toTuple(list:List[Any]):scala.Product = ...
Run Code Online (Sandbox Code Playgroud)

dhg*_*dhg 15

你真的不希望你的方法返回,Product因为这是无用的模糊.如果你想能够将返回的对象用作元组,那么你必须知道它的arity.所以你可以做的是toTupleN为不同的arities 提供一系列方法.为方便起见,您可以将这些添加为隐式方法Seq.

这个怎么样:

class EnrichedWithToTuple[A](elements: Seq[A]) {
  def toTuple2 = elements match { case Seq(a, b) => (a, b) }
  def toTuple3 = elements match { case Seq(a, b, c) => (a, b, c) }
  def toTuple4 = elements match { case Seq(a, b, c, d) => (a, b, c, d) }
  def toTuple5 = elements match { case Seq(a, b, c, d, e) => (a, b, c, d, e) }
}
implicit def enrichWithToTuple[A](elements: Seq[A]) = new EnrichedWithToTuple(elements)
Run Code Online (Sandbox Code Playgroud)

并使用它像:

scala> List(1,2,3).toTuple3
res0: (Int, Int, Int) = (1,2,3)
Run Code Online (Sandbox Code Playgroud)


Mil*_*bin 14

如果像@dhg观察到的那样,你知道预期的arity,你可以在这里做一些有用的事情.使用无形你可以写,

scala> import shapeless._
import shapeless._

scala> import Traversables._
import Traversables._

scala> import Tuples._
import Tuples._

scala> List(1, 2, 3).toHList[Int :: Int :: Int :: HNil] map tupled
res0: Option[(Int, Int, Int)] = Some((1,2,3))
Run Code Online (Sandbox Code Playgroud)


Kim*_*bel 11

如果你事先不知道arity并希望做一个可怕的糟糕黑客,你可以这样做:

def toTuple[A <: Object](as:List[A]):Product = {
  val tupleClass = Class.forName("scala.Tuple" + as.size)
  tupleClass.getConstructors.apply(0).newInstance(as:_*).asInstanceOf[Product]
}
toTuple: [A <: java.lang.Object](as: List[A])Product

scala> toTuple(List("hello", "world"))
res15: Product = (hello,world)
Run Code Online (Sandbox Code Playgroud)


0__*_*0__ 5

你想要一个Tuple还是仅仅一个Product。因为对于后者:

case class SeqProduct[A](elems: A*) {
  override def productArity: Int = elems.size
  override def productElement(i: Int) = elems(i)
}

SeqProduct(List(1, 2, 3): _*)
Run Code Online (Sandbox Code Playgroud)