2012-02-07 18 views
5

मान लीजिए कि मेरे पास Option[A => Boolean] है, List[A], और संचालन के कुछ सेट मैं उस सूची के उप-समूह पर प्रदर्शन करना चाहता हूं। यदि विकल्प सेट किया गया है, तो मैं पहले सूची को फ़िल्टर करना चाहता हूं और फिर अपने परिचालनों को लागू करना चाहता हूं। यदि नहीं, तो मैं इसे पूरी सूची में लागू करना चाहता हूं। एक उदाहरण:सशर्त रूप से एक अनुक्रम फ़िल्टर करें

val a : Option[Int => Boolean] = Option((a : Int) => a % 2 == 0) 
val b = 1 to 100 

मैं आसानी से निम्न कर सकते हैं:

val c = if (a.isDefined) b.filter(a.get) else b 

हालांकि, इस a.get बुला शामिल है; बहुत कंडीशनिंग मुझे ऐसा करने में असमर्थ छोड़ देता है! मैं वैकल्पिक रूप से कर सकता है:

val c = b.filter(a.getOrElse(_ => true)) 

यह बेहतर महसूस करता है, लेकिन अब मैं एक दूसरे (तुच्छ यद्यपि) आपरेशन मेरी अनुक्रम के प्रत्येक तत्व के लिए किया जा रहा के साथ फंस कर रहा हूँ। मैं उम्मीद कर सकता हूं कि इसे अनुकूलित किया जाएगा, लेकिन यह अभी भी अपूर्ण महसूस करता है।

मुझे क्या चाहिए कुछ दोष की कमी है। ऐसा लगता है कि ऐसा करने का एक अच्छा तरीका होना चाहिए - कोई विचार?

उत्तर

10

तुम बस सामान्य विकल्प से निपटने के तरीकों का उपयोग करने की जरूरत है:

a.map(b.filter).getOrElse(b) 
+0

हां; किसी कारण से मैं स्थिति को फिसलने के विचार को देखने में असफल रहा। यह बहुत साफ है। – Submonoid

+0

फिर भी एक और कारण है कि पैटर्न "option.map()। GetOrElse()" को मानक लाइब्रेरी में जोड़ा जाना चाहिए। यह हमेशा पहली चीजों में से एक है जिसमें मैं चिल्लाता हूं। –

+2

@ डेवग्रिफिथ - दरअसल। मेरे पास सिंटैक्स 'ओ.मैप (एफ) .getOrElse (बी)' ओ 'फोल्ड (बी) (एफ) 'के साथ' फोल्ड '(स्कालाज़ की तरह) कहा जाता है। –

1

कैसे के बारे में करने के लिए एक बदलते:

val a : Option[Seq[Int] => Seq[Int]] = Option((a : Seq[Int]) => a.filter(_ % 2 == 0)) 
val b = 1 to 100 
val c = a.getOrElse((f:Seq[Int]) => f)(b) 

(ध्यान दें मैं ऊपर प्रयास नहीं किया है, लेकिन यह आपको पता चलना चाहिए)

+0

आह, यह अच्छा लगता है! सूची के विकल्प के बजाय विकल्प को सूची में लागू करने के लिए स्थिति को फ़्लिप करने का विचार स्थिति को बहुत अच्छा बनाता है! पता था कि मैं कुछ याद कर रहा था। – Submonoid

3

असल में रेक्स Kerr के समाधान के रूप में एक ही है, लेकिन Scalaz से fold का उपयोग करता है यह थोड़ा अधिक संक्षिप्त बनाने के लिए।

सामान्य रूप से, x.fold(f, g)x.map(f).getOrElse(g)

scala> import scalaz._, Scalaz._ 
import scalaz._ 
import Scalaz._ 

scala> a.fold(b.filter, b) 
res112: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100) 
1

मैं व्यक्तिगत रूप से पैटर्न मिलान की स्पष्टता पसंद करता हूं; यह आपके गद्य विवरण से कोड में बहुत सी प्रत्यक्ष अनुवाद है:

val c = a match { 
    case Some(f) => b.filter(f) 
    case None => b 
} 
संबंधित मुद्दे