2014-10-08 8 views
12

मैं समझता हूँ कि कैसे स्केला आदेश और tuplesकैसे स्केल ऑर्डर tuples?

उदाहरण के लिए की छंटाई संभालती है, अगर मैं सूची

val l = for {i <- 1 to 5} yield (-i,i*2) 
Vector((-1,2), (-2,4), (-3,6), (-4,8), (-5,10)) 

स्केला जानता है कि यह कैसे सॉर्ट करने के लिए मिल गया कोशिश कर रहा हूँ:

l.sorted 
Vector((-5,10), (-4,8), (-3,6), (-2,4), (-1,2)) 

लेकिन tuple में '<' विधि नहीं है:

l.sortWith(_ < _) 

error: value < is not a member of (Int, Int) 
l.sortWith(_ < _) 

कैसे स्केल उन tuples को सॉर्ट करने के लिए पता है?

उत्तर

16

क्योंकि sorted एक अंतर्निहित पैरामीटर ord है:

डीईएफ़ अनुसार क्रमबद्ध [b>:] (अंतर्निहित ord: math.Ordering [बी]): सूची [एक] क्रमित इस क्रम एक आदेश के अनुसार ।

क्रमबद्ध है। यही है, तत्व जो बराबर हैं ( लेफ्टिनेंट द्वारा निर्धारित) क्रमबद्ध अनुक्रम में उसी क्रम में दिखाई देते हैं जैसे मूल में।

ord तत्वों की तुलना करने के लिए उपयोग करने के क्रम का आदेश।

और वहाँ एक अंतर्निहित रूपांतरण scala.math.Ordering में परिभाषित किया गया है:

implicit def Tuple2[T1, T2](implicit ord1: Ordering[T1], 
            ord2: Ordering[T2]): Ordering[(T1, T2)] 

तो l.sortedl.sorted(scala.math.Ordering.Tuple2[Int, Int]()) को परिवर्तित हो जाएगा।

टेस्ट यह:

scala> def catchOrd[A](xs: A)(implicit ord: math.Ordering[A]) = ord 
catchOrd: [A](xs: A)(implicit ord: scala.math.Ordering[A])scala.math.Ordering[A] 

scala> catchOrd((1,2)) 
res1: scala.math.Ordering[(Int, Int)] = [email protected] 

और निश्चित रूप से, आप कर सकते हैं परिभाषित अपनी खुद की Ordering:

scala> implicit object IntTupleOrd extends math.Ordering[(Int, Int)] { 
    | def compare(x: (Int, Int), y: (Int, Int)): Int = { 
    |  println(s"Hi, I am here with x: $x, y: $y") 
    |  val a = x._1*x._2 
    |  val b = y._1*y._2 
    |  if(a > b) 1 else if(a < b) -1 else 0 
    | } 
    | } 
defined object IntTupleOrd 

scala> Seq((1, 10), (3, 4), (2, 3)).sorted 
Hi, I am here with x: (1,10), y: (3,4) 
Hi, I am here with x: (3,4), y: (2,3) 
Hi, I am here with x: (1,10), y: (2,3) 
res2: Seq[(Int, Int)] = List((2,3), (1,10), (3,4)) 

संपादितTuple[Int, Int] समर्थन सभी निम्न विधियों में बनाने के लिए एक छोटी तरीका नहीं है: < , <=, >, >=

scala> implicit def mkOps[A](x: A)(implicit ord: math.Ordering[A]): ord.Ops = 
    | ord.mkOrderingOps(x) 
mkOps: [A](x: A)(implicit ord: scala.math.Ordering[A])ord.Ops 

scala> (1, 2) < (3, 4) 
res0: Boolean = true 

scala> (1, 2) <= (3, 4) 
res1: Boolean = true 

scala> (1, 2, 3) <= (1, 2, 4) 
res2: Boolean = true 

scala> (3, 3, 3, 3) >= (3, 3, 3, 4) 
res3: Boolean = false 
+0

मुझे नहीं पता। सॉर्टिंग टुपल्स कभी-कभी भ्रमित परिणामों का कारण बन सकती है। '(100 एल, 2 डी) :: (2 एल, 5001 डी) :: नील सॉर्टेड देता है: 'सूची ((2,5001.0), (100,2.0))'। ऐसा लगता है कि ट्यूपल के दूसरे तत्व पर कोई वेटेज नहीं है। – Ashesh

+3

आदेश केवल तभी के दूसरे तत्व को देखता है जब पहले तत्व बराबर होते हैं। – Ashesh

4

@ Eastsun का उत्तर अच्छी तरह से आपके प्रश्न के पहले भाग को बताता है "स्कैला सॉर्ट टुपल्स कैसे करता है"।

दूसरे भाग के बारे में

"क्यों एक < विधि है टपल नहीं है": स्काला में, तुलनाकारक < की तरह या तो (जब Int या Double आदि की तुलना) बुनियादी प्रकार के लिए देशी JVM तुलना करने के लिए अनुवाद या साथ सदस्य कार्यों के लिए someClass की प्रकार <(that: someClass): Boolean। यह मामला वास्तव में सिर्फ वाक्य रचनात्मक चीनी है: someObject < otherObjectsomeObject.<(otherObject) में अनुवाद करता है।आप tuples के लिए इस कार्यक्षमता करना चाहते हैं, तो आप गुंजाइश में एक अंतर्निहित वर्ग ला सकता है, और Ordering द्वारा प्रदान की तुलनाकारक की तुलना सदस्य समारोह नक्शा:

implicit class ProvideComparator[T](t1: T)(implicit ord: Ordering[T]) { 
    def <(t2: T) = ord.lt(t1, t2) 
    def >(t2: T) = ord.gt(t1, t2) // and so on 
} 

अब आप लिख सकते हैं:

scala> (1,2) < (2,2) 
res2: Boolean = true