कभी-कभी छोटे संग्रहों से टुपल्स बनाने की आवश्यकता होती है (उदाहरण के लिए ढेर ढांचे)।सूची से टुपल बनाने का कोई तरीका है (कोडजनरेशन के बिना)?
def toTuple(list:List[Any]):scala.Product = ...
कभी-कभी छोटे संग्रहों से टुपल्स बनाने की आवश्यकता होती है (उदाहरण के लिए ढेर ढांचे)।सूची से टुपल बनाने का कोई तरीका है (कोडजनरेशन के बिना)?
def toTuple(list:List[Any]):scala.Product = ...
आप सामने 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)
आप वास्तव में नहीं अपने विधि Product
वापस जाने के लिए के बाद से इस बेकार अस्पष्ट है चाहता हूँ। यदि आप लौटे ऑब्जेक्ट को टुपल के रूप में उपयोग करने में सक्षम होना चाहते हैं, तो आपको इसकी धैर्य जाननी होगी। तो आप क्या कर सकते हैं विभिन्न arities के लिए toTupleN
विधियों की एक श्रृंखला है। सुविधा के लिए, आप इन्हें 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)
और यह पसंद का उपयोग करें:
scala> List(1,2,3).toTuple3
res0: (Int, Int, Int) = (1,2,3)
हैं, के रूप में @dhg मनाया, आप की उम्मीद arity सामने तुम यहाँ कुछ उपयोगी कर सकते हैं पता है। shapeless आप लिख सकता है, का उपयोग करते हुए
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))
लेकिन 'यदि सूची की लंबाई संकलन समय में अपरिभाषित है Shapeless'' List' से एक 'Tuple' बनाने के लिए जिस तरह से प्रदान नहीं करता है, यह क्रम त्रुटियों –
आप चाहते हैं एक 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): _*)
का उपयोग भी कर सकते हैं' टुपल 'की भी इच्छा है, इसलिए मैं' FunctionX.tupled' का उपयोग कर सकता हूं, जिसे वास्तव में 'TupleX' की आवश्यकता होती है, 'उत्पाद' नहीं (नोट भी 'ProductX')। – metasim
@ किम स्टीबेल के विचार के आधार पर, मैंने एक सरल उपयोगिता लिखी जो सीक से ट्यूपल बनाता है।
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: _*)
}
}
धन्यवाद, @xKommando। यही वह चीज है जिसकी मुझे जरूरत थी। क्योंकि मैं _toTuple_ को _AnyRef_ के बजाय _Any_ के अनुक्रम पर लागू करने के लिए चाहता था, मैंने _Seq [Any] _ के साथ elems के प्रकार को प्रतिस्थापित किया और 'आकार <= 22' के लिए अभिव्यक्ति को' val refs = के लिए बदल दिया (e <- elems) उपज e.asInstanceOf [AnyRef] ctors (आकार - 1)। newInstance (refs: _ *)। asInstanceOf [product] '(यहां उत्तर के आधार पर: [link] (http://stackoverflow.com/questions/16751484/स्केला है कि कैसे करने के लिए बल-रैपिंग-एक-पूर्णांक के रूप में एक-वस्तु)) – Phasmid
+1 को साफ करने के लिए बहुत उपयोगी करने के लिए नेतृत्व कर सकते हैं तारों से असाइनमेंट। यह var (ए, बी, सी) = toTuple (myIter.toList) के लिए काम नहीं करता है - कोई विचार? –
रूबिस्ट्रो: उस उद्देश्य के लिए आप 'var list (a, b, c) = myIter.toList' –