আমি কীভাবে 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
চাইছেন তা দিয়ে সম্ভব না হলেও আপনি শেপলেস HList
টাইপের দিকে নজর রাখতে পারেন যা টিপলস ( github.com / মাইলেসাবিন /… ) থেকে রূপান্তর করতে দেয় । হতে পারে এটি আপনার ব্যবহারের ক্ষেত্রে প্রযোজ্য।
উত্তর:
আপনি টাইপসেফ উপায়ে এটি করতে পারবেন না। কেন? কারণ সাধারণভাবে আমরা রানটাইম পর্যন্ত কোনও তালিকার দৈর্ঘ্য জানতে পারি না। তবে একটি টিউপলের "দৈর্ঘ্য" অবশ্যই এটির মধ্যে এনকোড করা উচিত এবং তাই সংকলন সময়ে এটি পরিচিত। উদাহরণস্বরূপ, (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)
}
যা একটি tuple ফেরত
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
দ্রষ্টব্য: সংকলকটির এইচলিস্টে তালিকাটি রূপান্তর করতে কিছু প্রকারের তথ্য প্রয়োজন যে কারণে আপনাকে toHList
পদ্ধতিতে ধরণের তথ্য পাস করার কারণ প্রয়োজন
শেপলেস ২.০ কিছু সিনট্যাক্স পরিবর্তন করেছে। বর্ণহীন ব্যবহার করে এখানে আপডেট সমাধান।
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 টাইপ করার আগে টাইপটি নির্দিষ্ট করা উচিত। সাধারণত সাধারণত, যেহেতু টিপলগুলি তাদের ভদ্রতার মধ্যে সীমাবদ্ধ থাকে তাই আপনার সফ্টওয়্যারটির নকশাটি কোনও আলাদা সমাধান দ্বারা আরও ভালভাবে পরিবেশন করা হতে পারে।
তবুও, আপনি যদি স্ট্যাটিক্যালি একটি তালিকা তৈরি করে থাকেন, তবে এটির মতো একটি সমাধান বিবেচনা করুন, এছাড়াও নির্লজ্জ ব্যবহার করুন। এখানে, আমরা সরাসরি এইচএললিস্ট তৈরি করি এবং সংকলন টাইপটি উপলব্ধ। মনে রাখবেন যে এইচএললিস্টে তালিকার এবং টুপল উভয় প্রকারের বৈশিষ্ট্য রয়েছে। যেমন এটিতে বিভিন্ন ধরণের টিউপলের মতো উপাদান থাকতে পারে এবং স্ট্যান্ডার্ড সংগ্রহের মতো অন্যান্য ক্রিয়াকলাপের মধ্যে ম্যাপ করা যায়। 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))
আরেকটি সম্ভাবনা, যখন আপনি তালিকার নাম রাখতে চান না বা পুনরাবৃত্তি করতে চান না (আশা করি কেউ সিক / মাথার অংশগুলি এড়াতে কোনও উপায় দেখিয়ে দিতে পারেন):
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
সুতরাং আপনার যদি একই সমস্যা হয় তবে টিপলসের দরকার নেই।
val List(c1, c2, c3) = myList
আপনি টাইপ-নিরাপদ উপায়ে এটি করতে পারবেন না। স্কালায়, তালিকাগুলি হ'ল কিছু ধরণের উপাদানগুলির স্বেচ্ছাসেদী দৈর্ঘ্যের ক্রম। টাইপ সিস্টেমটি যতদূর জানে, x
স্বেচ্ছাসেবী দৈর্ঘ্যের একটি তালিকা হতে পারে।
বিপরীতে, একটি tuple এর শালীনতা সংকলন সময়ে জানা উচিত। এটি x
একটি টাইপল টাইপকে নির্ধারিত করার জন্য প্রকারের সুরক্ষা গ্যারান্টি লঙ্ঘন করবে ।
বস্তুত, প্রযুক্তিগত কারণের জন্য, Scala tuples 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 = List(1,2,3) match {case List(a, b, c) => (a, b, c)}
List
/ এর দৈর্ঘ্য Tuple
একটি পরিচিত ধ্রুবক হয়।
2015 পোস্ট। জন্য টম Crockett, এর উত্তর আরো হতে সে বিষয়ে পরিষ্কারভাবে বর্ণনা , এখানে একটি বাস্তব উদাহরণ।
প্রথমদিকে, আমি এটি সম্পর্কে বিভ্রান্ত হয়ে পড়েছিলাম। কারণ আমি পাইথন থেকে এসেছি, যেখানে আপনি কেবল পারেন tuple(list(1,2,3))
।
এটি স্কেলা ভাষার সংক্ষিপ্ত? (উত্তরটি হ'ল - এটি স্কেলা বা পাইথন সম্পর্কে নয়, এটি স্ট্যাটিক-টাইপ এবং ডায়নামিক-টাইপ সম্পর্কে))
এর ফলেই আমি স্কলার এটি করতে না পারার জন্য ক্রুক্সটি সন্ধান করার চেষ্টা করছি।
নিম্নলিখিত কোড উদাহরণটি একটি toTuple
পদ্ধতি প্রয়োগ করে , যা টাইপ-নিরাপদ toTupleN
এবং টাইপ-অনিরাপদ toTuple
।
toTuple
পদ্ধতি, রান সময়ে টাইপ দৈর্ঘ্যের তথ্য, কম্পাইল-সময়ে অর্থাত কোন প্রকার দৈর্ঘ্যের তথ্য পেতে তাই রিটার্ন টাইপ হয় Product
যা খুবই পাইথন এর মত হল tuple
প্রকৃতপক্ষে (কোন প্রতিটি অবস্থানে প্রকার, এবং ধরনের কোনো দৈর্ঘ)।
এই উপায়টি টাইপ-মিলহীন বা মত রানটাইম ত্রুটির সাথে যুক্ত হয় IndexOutOfBoundException
। (সুতরাং পাইথনের সুবিধাজনক তালিকা-থেকে-টুপল বিনামূল্যে লাঞ্চ নয় lunch)
বিপরীতে, এটি দৈর্ঘ্যের তথ্য সরবরাহকারী যা 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
, আর এর ধরণটি কী হওয়া উচিত?