scala 有没有办法从列表中创建元组(没有代码生成)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11305290/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there way to create tuple from list(without codegeneration)?
提问by yura
Sometimes there are needs to create tuples from small collections(for example scalding framework).
有时需要从小集合中创建元组(例如 scalding 框架)。
def toTuple(list:List[Any]):scala.Product = ...
采纳答案by Kim Stebel
If you don't know the arity up front and want to do a terrible terrible hack, you can do this:
如果你不知道前面的 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)
回答by dhg
You really don't want your method to return Productsince this is uselessly vague. If you want to be able to use the returned object as a tuple, then you'll have to know its arity. So what you can do is have a series of toTupleNmethods for different arities. For convenience, you can add these as implicit methods on Seq.
你真的不希望你的方法返回,Product因为这是无用的模糊。如果您希望能够将返回的对象用作元组,那么您必须知道它的数量。所以你可以做的是toTupleN对不同的参数有一系列的方法。为方便起见,您可以将这些作为隐式方法添加到 上Seq。
How about this:
这个怎么样:
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)
and use it like:
并像这样使用它:
scala> List(1,2,3).toTuple3
res0: (Int, Int, Int) = (1,2,3)
回答by Miles Sabin
If, as @dhg observed, you know the expected arity up front you can do something useful here. Using shapelessyou could write,
如果,正如@dhg 所观察到的,您预先知道预期的数量,那么您可以在这里做一些有用的事情。使用无形你可以写,
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))
回答by 0__
Do you want a Tupleor just a Product. Because for the latter:
你想要一个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): _*)
回答by xKommando
Based on @Kim Stebel's idea, I wrote a simple utility that creates tuple from seq.
基于@Kim Stebel 的想法,我编写了一个简单的实用程序,可以从 seq 创建元组。
import java.lang.reflect.Constructor
/**
* Created by Bowen Cai on 1/24/2015.
*/
sealed trait Product0 extends Any with Product {
def productArity = 0
def productElement(n: Int) = throw new IllegalStateException("No element")
def canEqual(that: Any) = false
}
object Tuple0 extends Product0 {
override def toString() = "()"
}
case class SeqProduct(elems: Any*) extends Product {
override def productArity: Int = elems.size
override def productElement(i: Int) = elems(i)
override def toString() = elems.addString(new StringBuilder(elems.size * 8 + 10), "(" , ",", ")").toString()
}
object Tuples {
private[this] val ctors = {
val ab = Array.newBuilder[Constructor[_]]
for (i <- 1 to 22) {
val tupleClass = Class.forName("scala.Tuple" + i)
ab += tupleClass.getConstructors.apply(0)
}
ab.result()
}
def toTuple(elems: Seq[AnyRef]): Product = elems.length match {
case 0 => Tuple0
case size if size <= 22 =>
ctors(size - 1).newInstance(elems: _*).asInstanceOf[Product]
case size if size > 22 => new SeqProduct(elems: _*)
}
}
回答by Lazy Developer
scala> val numbers = Seq(1,2,4)
numbers: Seq[Int] = List(1, 2, 4)
scala> val string = numbers.mkString("(",",",")")
string: String = (1,2,4)
*** mkString(start:String, sep: String, end: String)
I have generated it in my where-in-clause.
我已经在我的 where-in-clause 中生成了它。

