একটি স্কালার তালিকাটিকে একটি টুপলে রূপান্তর করবেন?


89

আমি কীভাবে 3 টি উপাদানের সাথে একটি তালিকা 3 আকারের টুপলে রূপান্তর করতে পারি?

উদাহরণস্বরূপ, ধরা যাক আমার আছে val x = List(1, 2, 3)এবং আমি এটিকে রূপান্তর করতে চাই (1, 2, 3)। কিভাবে আমি এটি করতে পারব?


4
এটি সম্ভব নয় ("হাত দ্বারা" বাদে) আফাইক। দেওয়া হল def toTuple(x: List[Int]): R, আর এর ধরণটি কী হওয়া উচিত?

7
যদি এটি কোনও x match { case a :: b :: c :: Nil => (a, b, c); case _ => (0, 0, 0) }Tuple3[Int,Int,Int]

4
আপনি যা করতে Listচাইছেন তা দিয়ে সম্ভব না হলেও আপনি শেপলেস HListটাইপের দিকে নজর রাখতে পারেন যা টিপলস ( github.com / মাইলেসাবিন /… ) থেকে রূপান্তর করতে দেয় । হতে পারে এটি আপনার ব্যবহারের ক্ষেত্রে প্রযোজ্য।

উত্তর:


59

আপনি টাইপসেফ উপায়ে এটি করতে পারবেন না। কেন? কারণ সাধারণভাবে আমরা রানটাইম পর্যন্ত কোনও তালিকার দৈর্ঘ্য জানতে পারি না। তবে একটি টিউপলের "দৈর্ঘ্য" অবশ্যই এটির মধ্যে এনকোড করা উচিত এবং তাই সংকলন সময়ে এটি পরিচিত। উদাহরণস্বরূপ, (1,'a',true)টাইপ আছে (Int, Char, Boolean)যা চিনির জন্য Tuple3[Int, Char, Boolean]। টিপলসগুলির এই বিধিনিষেধের কারণ হ'ল তাদের একটি অ-সমজাতীয় ধরণের হ্যান্ডেল করতে সক্ষম হওয়া দরকার।


একই ধরণের উপাদানগুলির কিছু স্থির-আকারের তালিকা রয়েছে? অবশ্যই নিরাকার মতো নন-স্ট্যান্ডার্ড লাইব্রেরি আমদানি করবেন না।

4
@ ডেভিপগুলি আমি জানি না, তবে এটি নিজের তৈরি করা যথেষ্ট সহজ, যেমনcase class Vec3[A](_1: A, _2: A, _3: A)
টম ক্রকেট

এটি একই ধরণের উপাদানগুলির একটি "টুপল" হবে, উদাহরণস্বরূপ, আমি এটিতে মানচিত্র প্রয়োগ করতে পারি না।

4
@ ডেভিপগুলি কোনও নতুন ডেটা টাইপের মতোই আপনাকে এটি নির্ধারণ করতে mapহবে যে এর জন্য কীভাবে কাজ করে
টম ক্রকেট

4
এই জাতীয় সীমাবদ্ধতা অন্য যে কোনও কিছুর চেয়ে ধরণের সুরক্ষার অকেজোতার একটি সূচকীয় সূচক বলে মনে হয়। এটি আমার উদ্ধৃতিটির কথা মনে করিয়ে দেয় "খালি সেটটিতে অনেক আকর্ষণীয় বৈশিষ্ট্য রয়েছে।"
এলী

58

আপনি এটি স্কেল এক্সট্র্যাক্টর এবং প্যাটার্ন ম্যাচিং ( লিঙ্ক ) ব্যবহার করে করতে পারেন :

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)
}

4
এই সমাধানের প্রসঙ্গে, টাইপ-সুরক্ষা সম্পর্কে অভিযোগের অর্থ আপনি রানটাইমটিতে ম্যাচএরর পেতে পারেন। আপনি যদি চান তবে আপনি সেই ত্রুটিটি ধরতে চেষ্টা করতে পারেন এবং তালিকার ভুল দৈর্ঘ্য থাকলে কিছু করতে পারেন। এই সমাধানটির আর একটি দুর্দান্ত বৈশিষ্ট্য হ'ল আউটপুট টিউপল হতে হবে না, এটি আপনার নিজস্ব কাস্টম ক্লাসগুলির একটি হতে পারে বা সংখ্যার কিছু রূপান্তর। আমি মনে করি না আপনি এটি অ-তালিকাগুলির সাহায্যে করতে পারেন, যদিও (সুতরাং আপনাকে ইনপুটটিতে .toList অপারেশন করতে হতে পারে)।
জিম পিভারস্কি

আপনি +: সিনট্যাক্স ব্যবহার করে যে কোনও ধরণের স্কালার ক্রম দিয়ে এটি করতে পারেন। এছাড়াও, একটি ক্যাচ-অল যুক্ত করতে ভুলবেন না
ig-dev

48

নিরাকার ব্যবহার করে একটি উদাহরণ :

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পদ্ধতিতে ধরণের তথ্য পাস করার কারণ প্রয়োজন


19

শেপলেস ২.০ কিছু সিনট্যাক্স পরিবর্তন করেছে। বর্ণহীন ব্যবহার করে এখানে আপডেট সমাধান।

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)

13

সরলতা থাকা সত্ত্বেও এবং কোনও দৈর্ঘ্যের তালিকার জন্য নয়, এটি টাইপ-নিরাপদ এবং বেশিরভাগ ক্ষেত্রেই উত্তর:

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

10

এফডাব্লুআইডাব্লু, আমি বেশ কয়েকটি ক্ষেত্রের সূচনা করতে টিউপল চাইছিলাম এবং টুপল অ্যাসাইনমেন্টের সিনট্যাকটিক চিনি ব্যবহার করতে চাই। ইজি:

val (c1, c2, c3) = listToTuple(myList)

দেখা যাচ্ছে যে তালিকার বিষয়বস্তুগুলিকেও নির্ধারিত করার জন্য সিনট্যাকটিক চিনি রয়েছে ...

val c1 :: c2 :: c3 :: Nil = myList

সুতরাং আপনার যদি একই সমস্যা হয় তবে টিপলসের দরকার নেই।


@ জাভাদ্বা আমি কীভাবে তালিকার টুপল () প্রয়োগ করতে হবে তা সন্ধান করছিলাম তবে শেষ হওয়ার দরকার নেই। তালিকা সিনট্যাকটিক চিনি আমার সমস্যার সমাধান করেছে।
পিটার এল

আরও একটি বাক্য গঠন রয়েছে, যা আমার মতে কিছুটা ভাল দেখাচ্ছে:val List(c1, c2, c3) = myList
কলমার

7

আপনি টাইপ-নিরাপদ উপায়ে এটি করতে পারবেন না। স্কালায়, তালিকাগুলি হ'ল কিছু ধরণের উপাদানগুলির স্বেচ্ছাসেদী দৈর্ঘ্যের ক্রম। টাইপ সিস্টেমটি যতদূর জানে, xস্বেচ্ছাসেবী দৈর্ঘ্যের একটি তালিকা হতে পারে।

বিপরীতে, একটি tuple এর শালীনতা সংকলন সময়ে জানা উচিত। এটি xএকটি টাইপল টাইপকে নির্ধারিত করার জন্য প্রকারের সুরক্ষা গ্যারান্টি লঙ্ঘন করবে ।

বস্তুত, প্রযুক্তিগত কারণের জন্য, Scala tuples 22 উপাদান সীমাবদ্ধ ছিল , কিন্তু সীমা আর 2.11 মামলা বর্গ সীমা 2.11 মধ্যে প্রত্যাহার করা হয়েছে বিদ্যমান https://github.com/scala/scala/pull/2305

ম্যানুয়ালি এমন কোনও ফাংশন কোড করা সম্ভব হবে যা 22 টি পর্যন্ত উপাদানগুলির তালিকাকে রূপান্তর করে এবং বৃহত তালিকার ব্যতিক্রম ছুঁড়ে ফেলে। স্কালার টেমপ্লেট সমর্থন, একটি আসন্ন বৈশিষ্ট্য এটি আরও সংক্ষিপ্ত করে তুলবে। তবে এটি একটি কুৎসিত হ্যাক হবে।


এই অনুমানমূলক কার্যকারিতার ফলে প্রাপ্ত ধরণটি কি কোনও হবে?

কেস শ্রেণির সীমা 2.11 github.com/scala/scala/pull/2305
gdoubleod

5

যদি আপনি খুব নিশ্চিত হন যে আপনার তালিকাটি <সাইজ <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)

5

এটি 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) হতে হবে ।


এটি 22 টিরও বেশি আকারের আকারে কাজ করবে না বলে মনে হচ্ছে, কমপক্ষে
নিরলস 2.11

@ কেফখালিলি হ্যাঁ, এবং এটি নিরর্থক সীমাবদ্ধতা নয়। স্কালা 2 নিজেই 22 টিরও বেশি উপাদানগুলির সাথে টুপলগুলিকে মঞ্জুরি দেয় না, সুতরাং কোনও পদ্ধতি ব্যবহার করে বড় আকারের তালিকাকে একটি টুপলে রূপান্তর করা সম্ভব নয়।
কলমার

4

প্যাটার্ন ম্যাচিং ব্যবহার:

val intTuple = List(1,2,3) match {case List(a, b, c) => (a, b, c)}

এই পুরানো কোনও প্রশ্নের উত্তর দেওয়ার সময় (years বছরেরও বেশি সময় ধরে) ইতিমধ্যে জমা দেওয়া সমস্ত (12) পুরানো উত্তরগুলির চেয়ে আপনার উত্তর কীভাবে আলাদা তা উল্লেখ করা প্রায়শই ভাল ধারণা। বিশেষত, আপনার উত্তরটি কেবলমাত্র প্রযোজ্য যদি List/ এর দৈর্ঘ্য Tupleএকটি পরিচিত ধ্রুবক হয়।
jwvh

আপনাকে @ jwvh ধন্যবাদ, আপনার মন্তব্যগুলি এগিয়ে যাওয়ার বিষয়ে বিবেচনা করবে।
মাইকেল ওলাফিসয়ে

2

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!

দেখতে দুর্দান্ত
লাগছে

2

আপনি এটি করতে পারেন

  1. প্যাটার্ন-ম্যাচিংয়ের মাধ্যমে (যা আপনি চান না) বা
  2. তালিকাটি পুনরাবৃত্তি করে এবং প্রতিটি উপাদানকে একে একে প্রয়োগ করে।

    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)]
    

1

যতক্ষণ আপনার টাইপ রয়েছে:

val x: List[Int] = List(1, 2, 3)

def doSomething(a:Int *)

doSomething(x:_*)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.