मैं 3 तत्वों के साथ एक सूची को आकार 3 के टपल में कैसे बदल सकता हूं?
उदाहरण के लिए, मान लें कि मेरे पास है val x = List(1, 2, 3)
और मैं इसे रूपांतरित करना चाहता हूं (1, 2, 3)
। मैं यह कैसे कर सकता हूँ?
मैं 3 तत्वों के साथ एक सूची को आकार 3 के टपल में कैसे बदल सकता हूं?
उदाहरण के लिए, मान लें कि मेरे पास है val x = List(1, 2, 3)
और मैं इसे रूपांतरित करना चाहता हूं (1, 2, 3)
। मैं यह कैसे कर सकता हूँ?
x match { case a :: b :: c :: Nil => (a, b, c); case _ => (0, 0, 0) }
और नोट करें कि परिणामी प्रकार तय हो गया हैTuple3[Int,Int,Int]
List
, तो आप Shapeless ' HList
प्रकार में देख सकते हैं , जो कि tuples ( github.com/milessabin/… ) से रूपांतरण की अनुमति देता है । शायद यह आपके उपयोग के मामले के लिए लागू हो।
जवाबों:
आप इसे एक प्रकार से नहीं कर सकते। क्यों? क्योंकि सामान्य तौर पर हम रनटाइम तक किसी सूची की लंबाई नहीं जान सकते। लेकिन एक टपल की "लंबाई" को इसके प्रकार में एन्कोड किया जाना चाहिए, और इसलिए संकलन समय पर जाना जाता है। उदाहरण के लिए, (1,'a',true)
प्रकार है (Int, Char, Boolean)
, जो चीनी के लिए है Tuple3[Int, Char, Boolean]
। ट्यूपल्स के कारण यह प्रतिबंध है कि उन्हें गैर-सजातीय प्रकारों को संभालने में सक्षम होने की आवश्यकता है।
case class Vec3[A](_1: A, _2: A, _3: A)
map
आदि इसके लिए कैसे काम करता है
आप इसे स्काला एक्सट्रैक्टर्स और पैटर्न मैचिंग ( लिंक ) का उपयोग करके कर सकते हैं :
val x = List(1, 2, 3)
val t = x match {
case List(a, b, c) => (a, b, c)
}
जो टपल लौटाता है
t: (Int, Int, Int) = (1,2,3)
इसके अलावा, यदि आप सूची के आकार के बारे में निश्चित नहीं हैं, तो आप वाइल्डकार्ड ऑपरेटर का उपयोग कर सकते हैं
val t = x match {
case List(a, b, c, _*) => (a, b, c)
}
निराकार का उपयोग कर एक उदाहरण :
import shapeless._
import syntax.std.traversable._
val x = List(1, 2, 3)
val xHList = x.toHList[Int::Int::Int::HNil]
val t = xHList.get.tupled
नोट: कंपाइलर को HList में सूची बदलने के लिए कुछ प्रकार के informations की आवश्यकता होती है, यही कारण है कि आपको toHList
विधि में टाइप informations को पास करने की आवश्यकता है
शापलेस 2.0 ने कुछ सिंटैक्स को बदल दिया। यहां आकारहीन का उपयोग करके अद्यतन समाधान है।
import shapeless._
import HList._
import syntax.std.traversable._
val x = List(1, 2, 3)
val y = x.toHList[Int::Int::Int::HNil]
val z = y.get.tupled
मुख्य मुद्दा यह है कि प्रकार .toHList के लिए को समय से पहले निर्दिष्ट किया जाना चाहिए। अधिक आम तौर पर, चूंकि टूपल उनकी धमनी में सीमित होते हैं, इसलिए आपके सॉफ़्टवेयर का डिज़ाइन एक अलग समाधान द्वारा बेहतर ढंग से परोसा जा सकता है।
फिर भी, यदि आप एक सूची को वैधानिक रूप से बना रहे हैं, तो इस तरह के एक समाधान पर विचार करें, आकारहीन का उपयोग करके भी। यहां, हम सीधे एक HList बनाते हैं और संकलन समय पर उपलब्ध होता है। याद रखें कि एक HList में सूची और Tuple दोनों प्रकार की विशेषताएं हैं। अर्थात इसमें टपल की तरह विभिन्न प्रकार के तत्व हो सकते हैं और मानक संग्रह जैसे अन्य कार्यों के बीच मैप किए जा सकते हैं। HLists थोड़ा समय लेते हैं, हालांकि आप नए हैं तो धीरे-धीरे चलने के लिए उपयोग करें।
scala> import shapeless._
import shapeless._
scala> import HList._
import HList._
scala> val hlist = "z" :: 6 :: "b" :: true :: HNil
hlist: shapeless.::[String,shapeless.::[Int,shapeless.::[String,shapeless.::[Boolean,shapeless.HNil]]]] = z :: 6 :: b :: true :: HNil
scala> val tup = hlist.tupled
tup: (String, Int, String, Boolean) = (z,6,b,true)
scala> tup
res0: (String, Int, String, Boolean) = (z,6,b,true)
सादगी और किसी भी लंबाई की सूचियों के लिए नहीं होने के बावजूद, यह टाइप-सेफ है और ज्यादातर मामलों में इसका जवाब है:
val list = List('a','b')
val tuple = list(0) -> list(1)
val list = List('a','b','c')
val tuple = (list(0), list(1), list(2))
एक और संभावना है, जब आप सूची को नाम नहीं देना चाहते हैं और न ही इसे दोहराना चाहते हैं (मुझे आशा है कि कोई व्यक्ति Seq / अन्य भागों से बचने का कोई रास्ता दिखा सकता है):
val tuple = Seq(List('a','b')).map(tup => tup(0) -> tup(1)).head
val tuple = Seq(List('a','b','c')).map(tup => (tup(0), tup(1), tup(2))).head
एफडब्ल्यूआईडब्ल्यू , मुझे कई क्षेत्रों में ट्यूलल चाहिए था और टपल असाइनमेंट के सिंटैक्टिक शुगर का उपयोग करना चाहता था। ईजी:
val (c1, c2, c3) = listToTuple(myList)
यह पता चला है कि एक सूची की सामग्री को भी असाइन करने के लिए वाक्य रचना चीनी है ...
val c1 :: c2 :: c3 :: Nil = myList
तो अगर आप एक ही समस्या है tuples के लिए कोई ज़रूरत नहीं है।
val List(c1, c2, c3) = myList
आप इसे एक प्रकार से सुरक्षित तरीके से नहीं कर सकते। स्काला में, सूचियाँ कुछ प्रकार के तत्वों के मनमाने ढंग से लंबाई वाले अनुक्रम हैं। जहाँ तक प्रकार प्रणाली को जानता है,x
वह मनमानी लंबाई की सूची हो सकती है।
इसके विपरीत, एक टपल की समता को संकलन समय पर जाना जाना चाहिए। यह असाइन करने की अनुमति देने के लिए प्रकार प्रणाली की सुरक्षा गारंटी का उल्लंघन करेगाx
टपल प्रकार को करने की ।
वास्तव में, तकनीकी कारणों से, स्केल ट्यूपल 22 तत्वों तक सीमित थे , लेकिन सीमा अब 2.11 में मौजूद नहीं है। 2.11 में केस क्लास की सीमा को हटा दिया गया है। https://github.com/scala/scala/pull/2305
एक फ़ंक्शन को मैन्युअल रूप से कोड करना संभव होगा जो 22 तत्वों की सूचियों को परिवर्तित करता है, और बड़ी सूची के लिए एक अपवाद फेंकता है। स्काला का टेम्पलेट समर्थन, एक आगामी विशेषता, इसे और अधिक संक्षिप्त बना देगा। लेकिन यह एक बदसूरत हैक होगा।
यदि आप बहुत सुनिश्चित हैं कि आपकी सूची। 23 का उपयोग करें:
def listToTuple[A <: Object](list:List[A]):Product = {
val class = Class.forName("scala.Tuple" + list.size)
class.getConstructors.apply(0).newInstance(list:_*).asInstanceOf[Product]
}
listToTuple: [A <: java.lang.Object](list: List[A])Product
scala> listToTuple(List("Scala", "Smart"))
res15: Product = (Scala,Smart)
इसका shapeless
उपयोग कम बॉयलरप्लेट के साथ भी किया जा सकता है Sized
:
scala> import shapeless._
scala> import shapeless.syntax.sized._
scala> val x = List(1, 2, 3)
x: List[Int] = List(1, 2, 3)
scala> x.sized(3).map(_.tupled)
res1: Option[(Int, Int, Int)] = Some((1,2,3))
यह टाइप-सुरक्षित है: आपको मिलता है None
, अगर टपल का आकार गलत है, लेकिन टपल का आकार एक शाब्दिक या final val
(परिवर्तनीय होना चाहिए shapeless.Nat
) होना चाहिए ।
पैटर्न मिलान का उपयोग करना:
val intTuple = सूची (1,2,3) मैच {केस सूची (ए, बी, सी) => (ए, बी, सी)}
List
/ की लंबाई Tuple
एक ज्ञात स्थिरांक हो।
2015 की पोस्ट। के लिए टॉम Crockett का जवाब भी अधिक होने की स्पष्ट है, यहाँ कोई वास्तविक उदाहरण है।
सबसे पहले, मैं इसके बारे में भ्रमित हो गया। क्योंकि मैं पायथन से आता हूं, जहां आप बस कर सकते हैं tuple(list(1,2,3))
।
क्या यह स्काला भाषा से कम है? (उत्तर है - यह स्काला या पायथन के बारे में नहीं है, यह स्थैतिक-प्रकार और गतिशील-प्रकार के बारे में है।)
यही कारण है कि मुझे क्रूक्स को खोजने की कोशिश कर रहा है कि स्काला ऐसा क्यों नहीं कर सकता है।
निम्न कोड उदाहरण एक toTuple
विधि को लागू करता है, जिसमें टाइप-सेफ toTupleN
और टाइप-असुरक्षित है toTuple
।
toTuple
विधि, रन-टाइम में टाइप-लंबाई सूचना संकलन समय पर यानी कोई प्रकार- लंबाई जानकारी प्राप्त तो वापसी प्रकार है Product
जो बहुत ही अजगर की तरह है tuple
वास्तव में (कोई प्रत्येक स्थिति में प्रकार, और प्रकार की कोई लंबाई)।
उस प्रकार को रनटाइम त्रुटि के लिए टाइप-मिसमैच या कहा जाता हैIndexOutOfBoundException
। (इसलिए पायथन की सुविधाजनक सूची-टू-ट्यूपल मुफ्त दोपहर का भोजन नहीं है।)
इसके विपरीत, यह उपयोगकर्ता द्वारा प्रदान की गई लंबाई की जानकारी है जो toTupleN
संकलन-समय को सुरक्षित बनाती है।
implicit class EnrichedWithToTuple[A](elements: Seq[A]) {
def toTuple: Product = elements.length match {
case 2 => toTuple2
case 3 => toTuple3
}
def toTuple2 = elements match {case Seq(a, b) => (a, b) }
def toTuple3 = elements match {case Seq(a, b, c) => (a, b, c) }
}
val product = List(1, 2, 3).toTuple
product.productElement(5) //runtime IndexOutOfBoundException, Bad !
val tuple = List(1, 2, 3).toTuple3
tuple._5 //compiler error, Good!
आप भी ऐसा कर सकते हैं
सूची के माध्यम से पुनरावृत्ति और प्रत्येक तत्व को एक-एक करके लागू करना।
val xs: Seq[Any] = List(1:Int, 2.0:Double, "3":String)
val t: (Int,Double,String) = xs.foldLeft((Tuple3[Int,Double,String] _).curried:Any)({
case (f,x) => f.asInstanceOf[Any=>Any](x)
}).asInstanceOf[(Int,Double,String)]
def toTuple(x: List[Int]): R
, R का प्रकार क्या होना चाहिए?