2013-03-22 4 views
6

संपादित करें: मैं बस याद रख लिया है समतल है कि मेरे फिल्टर के रूप में एक ही प्रभाव पड़ता है औरस्काला सशर्त सूची निर्माण

मैं स्काला 2.9.2 का उपयोग कर रहा नक्शा, और कुछ शर्तों के आधार पर सूची का निर्माण करना चाहते हैं।

, निम्नलिखित पर विचार करें जहां cond (इस मामले t3 में) एक विधेय पी और प्रकार टी के एक मूल्य लेने कुछ कार्य है:

t1 :: t2 :: cond(p, t3) :: t4 

व्यवहार मैं चाहता हूँ इस प्रकार है। अगर p सच है, यह देना चाहिए:

List[T](t1, t2, t3, t4) 

पी गलत का आकलन करते हैं, तो यह देना चाहिए:

List[T](t1, t2, t4) 

मैं शायद यह पूरी तरह से गलत तरीके के बारे में सोच रहा हूँ, लेकिन मैं संघर्ष कर रहा हूँ एक सुरुचिपूर्ण समाधान के साथ आने के लिए। मैं विकल्प हर जगह शामिल हो सकता है और उसके बाद से फिल्टर, लेकिन वह यह पढ़ने के लिए कोड नहीं बल्कि कठिन बना देता है:

def cond[T](p : => Boolean, v : T) : Option[T] = 
{ 
    p match 
    { 
     case true => Some(v) 
     case false => None 
    } 
} 

यह निम्न अनुमति देता है:

scala> (Some(1) :: Some(2) :: cond(true, 3) :: Some(4) :: Nil).flatten 
res4: List[Int] = List(1, 2, 3, 4) 

scala> (Some(1) :: Some(2) :: cond(false, 3) :: Some(4) :: Nil).flatten 
res5: List[Int] = List(1, 2, 4) 

हालांकि, यह, सबसे खूबसूरत समाधान नहीं है के रूप में यह आवश्यकता है उपयोगकर्ता कुछ() में अपने सभी गैर-सशर्त तत्वों को लपेटने के लिए और अंत में फ़्लैटन को याद रखना भी याद रखता है। क्या कोई और अधिक सुरुचिपूर्ण समाधान के बारे में सोच सकता है?

उत्तर

5

एक सूची देने के बारे में कैसे?

@inline def cond[T](p : => Boolean, v : T) : List[T] = if(p) v::Nil else Nil 

और फिर इस रूप में उन्हें का उपयोग कर:

List(1,2,3) ++ cond(false, 3) ++ List(4) 
+0

यह काम करता है, लेकिन यह आदर्श नहीं है, क्योंकि यह 1 :: 2 :: 3 निर्माण विधि के साथ फिट नहीं है: इसके लिए आपको ++ कुछ मामलों में :: – paulmdavies

4

बनाने का प्रयास करें और अपने शर्त के साथ नई सूची को फ़िल्टर:

List[T](t1, t2, t3, t4).filter(p) 
+1

के बजाय यह सामान्य मामले में काम नहीं करता है - स्थिति p_i तत्व t_i के लिए विशिष्ट है - और p_i का मूल्यांकन करने का परिणाम केवल तभी प्रभावित होना चाहिए कि t_i सूची में है, t_j नहीं, जहां j! = मैं – paulmdavies

0

आप सूचकांक पता करने के लिए उचित चयन करने के लिए की जरूरत है अनुमान लगाएं, आप zipWithIndex मानों के साथ सूचकांक को जोड़ने के लिए collect का उपयोग collect का उपयोग कर सकते हैं ताकि आप इंडेक्स को परिणाम से छोड़ दें और पूर्व को एन्कोड कर सकें एक गार्ड में icate चयन और आवेदन। उदाहरण के लिए:

List(1, 4, 9, 16, 25).zipWithIndex.collect { case (n, i) if (n + i) % 3 <= 1 => n } 
res0: List[Int] = List(1, 16) 
3

तो, कोई रास्ता नहीं इस मानक सूची के साथ काम करेंगे, क्योंकि प्रकार गलत कर रहे हैं:, :: प्रकार [A >: T] का एक तत्व जहां T सूची प्रकार है उम्मीद है, जबकि आप इसे कुछ देना चाहता हूँ कि हो सकता है, या नहीं, उस प्रकार का एक तत्व उत्पन्न कर सकते हैं।

हालांकि, ऐसा कोई कारण नहीं है कि कोई ऐसी विधि को परिभाषित करने में सक्षम न हो जो कुछ ऐसा करने में काफी खुश हो जो वैकल्पिक रूप से वैकल्पिक तत्व उत्पन्न करता हो। List ही बंद है, इसलिए हम इसे सीधे विस्तार कर सकते हैं नहीं है, लेकिन हम व्यवहार हम काफी आसानी से की जरूरत को दोहराने कर सकते हैं:

trait QList[+T] { 

    def hd : T 
    def tl : QList[T] 

    def ?::[A >: T](hd : A) : QList[A] = new ?::[A](hd, this) 
    def ?::[A >: T](hd : => Option[A]) : QList[A] = hd match { 
    case Some(a) => ?::(a) 
    case None => this 
    } 
} 

case object QNil extends QList[Nothing] { 
    def hd = throw new Exception("Head of empty list") 
    def tl = throw new Exception("Tail of empty list") 
} 
case class ?::[+T](val hd: T, val tl : QList[T]) extends QList[T] 

def cond[T](p : => Boolean, v : T) : Option[T] = 
{ 
    p match 
    { 
    case true => Some(v) 
    case false => None 
    } 
} 

val truelist = 1 ?:: 2 ?:: 3 ?:: cond(true, 4) ?:: 5 ?:: QNil 
val falselist = 1 ?:: 2 ?:: 3 ?:: cond(false, 4) ?:: 5 ?:: QNil 

हम मूल रूप से पुनः सूची है, लेकिन एक ओवरलोड आगे जोड़ते आपरेशन कि एक शर्त लेता है के साथ रंगना ।

सही विधि वाले किसी अन्य वर्ग में एक अंतर्निहित रूपांतरण का उपयोग करके मानक सूची में ?:: विधि जोड़ना संभव है। आप 2.9.2, क्योंकि अन्यथा यह बात यह है कि निहित मूल्य वर्गों के लिए महान हैं की तरह है जो शर्म की बात है का उपयोग कर रहे उल्लेख, लेकिन हम उन्हें जरूरत नहीं है, वे तो बस चीजों को आसान बनाने:

class ConditionallyAppend[T](tl : List[T]) { 
    def ?::[A >: T](hd : A) : List[A] = hd :: tl 
    def ?::[A >: T](x : => Option[A]) : List[A] = x match { 
    case Some(a) => a :: tl 
    case None => tl 
    } 
} 

implicit def ListToConditionallyAppend[A](x : List[A]) = new ConditionallyAppend(x) 

और अब हम ऐसा कर सकते हैं??

वैल truelist = 1 :: 2 :: 3 :: cond (सच, 4) :: 5 :: कोई नहीं

truelist? सूची [कोई भी] = सूची (1, 2, 3, 4, 5)

और यह??

वैल falselist = 1 :: 2 :: 3 :: cond (गलत, 4) :: 5 :: कोई नहीं

falselist? सूची [कोई] = सूची (1, 2, 3, 5)

+0

मैं briefl y ने यह सुझाव देने के लिए संपादित किया कि हम '? ::' जोड़ने के बजाय डिफ़ॉल्ट ':: 'ऑपरेटर को ओवरराइड कर सकते हैं। हम कर सकते हैं, लेकिन यह काफी काम नहीं करता है। चूंकि 'सूची' कॉन्व्रैंट है, मानक प्रीपेड कुछ भी स्वीकार करेगा जो इसे सुपर प्रकार के रूप में अनुमानित कर सकता है, और इसलिए आपको केवल' कोई नहीं '' सूची में 'कोई भी' नहीं देगा। – Impredicative