2014-09-25 7 views
5

में ट्रैवर्सबल में 1 से अधिक तत्व होने की जांच करने का कुशल तरीका मुझे यह जांचना होगा कि Traversable (जो मुझे पहले से ही nonEmpty होना है) में एक तत्व या अधिक है।स्केल

मैं size का उपयोग कर सकता हूं, लेकिन (मुझे बताएं कि क्या मैं गलत हूं) मुझे संदेह है कि यह ओ (एन) हो सकता है, और गणना करने के लिए संग्रह को पार कर सकता है।

मैं अगर tail.nonEmpty जांच कर सकता है, या यदि .head != .last

कौन सा पेशेवरों और दो दृष्टिकोण के विपक्ष कर रहे हैं? क्या कोई बेहतर तरीका है? (उदाहरण के लिए, .last एक पूर्ण पुनरावृत्ति भी करेगा?)

उत्तर

7

सभी दृष्टिकोण है कि संग्रह की शुरुआत से तत्वों में कटौती और वापसी पूंछ अक्षम हैं। उदाहरण के लिए tailList के लिए ओ (1) है, जबकि tailArray के लिए ओ (एन) है। drop के साथ ही।

मैं take का उपयोग कर का प्रस्ताव:

list.take(2).size == 1 // list is singleton 

take पूरे संग्रह वापस जाने के लिए करता है, तो संग्रह की लंबाई कम है कि take का तर्क है की घोषणा की है। इस प्रकार संग्रह खाली होने पर या केवल एक तत्व होने पर कोई त्रुटि नहीं होगी। दूसरी तरफ यदि संग्रह विशाल है take फिर भी (1) समय में चलाएगा। आंतरिक रूप से take आपके संग्रह को फिर से शुरू करना शुरू कर देगा, दो चरणों को ले जाएगा और ब्रेक करेगा, नए संग्रह में तत्वों को वापस लौटाएगा।

युपीडी: मैं हालत बदल वास्तव में सवाल

+2

आप के साथ 'दृश्य (0,2) .size' किसी भी संग्रह के निर्माण से बच सकते हैं। –

3

सभी समान नहीं होंगे, लेकिन चलिए एक सबसे खराब स्थिति परिदृश्य लेते हैं जहां यह List है। last उस तत्व तक पहुंचने के लिए पूरे List का उपभोग करेगा, जैसा कि size होगा।

tail.nonEmptyhead :: tail पैटर्न मिलान से प्राप्त किया गया है, जिसे पूरे List का उपभोग करने की आवश्यकता नहीं है। यदि आप पहले ही सूची को खाली नहीं जानते हैं, तो यह स्पष्ट विकल्प होना चाहिए।

लेकिन सभी tail संचालन एक List की तरह निरंतर समय लगेगा: Scala Collections Performance

0

क्या पैटर्न मिलान के बारे में मैच के लिए?

itrbl match { case _::Nil => "one"; case _=>"more" } 
+0

क्या यह .tail.nonEmpty का उपयोग करने जैसा नहीं है? निश्चित रूप से, आप तर्क दे सकते हैं कि यह अधिक सुरुचिपूर्ण है ... –

+0

दरअसल, मुझे लगता है कि यह दो बार कॉल करने की तरह होना चाहिए जो itetable.iterator.next में अनुवाद करता है जबकि tail.isEmpty iterator.next iterator.hasNext जैसा दिखता है – Azzie

1

आप एक ट्रैवर्सबल का दृश्य ले सकते हैं। आप TraversableView आलसी ढंग से टुकड़ा कर सकते हैं।

प्रारंभिक सितारा इसलिए है क्योंकि आरईपीएल कुछ आउटपुट प्रिंट करता है।

scala> val t: Traversable[Int] = Stream continually { println("*"); 42 } 
* 
t: Traversable[Int] = Stream(42, ?) 

scala> t.view.slice(0,2).size 
* 
res1: Int = 2 

scala> val t: Traversable[Int] = Stream.fill(1) { println("*"); 42 } 
* 
t: Traversable[Int] = Stream(42, ?) 

scala> t.view.slice(0,2).size 
res2: Int = 1 

लाभ यह है कि कोई मध्यवर्ती संग्रह नहीं है।

scala> val t: Traversable[_] = Map((1 to 10) map ((_, "x")): _*) 
t: Traversable[_] = Map(5 -> x, 10 -> x, 1 -> x, 6 -> x, 9 -> x, 2 -> x, 7 -> x, 3 -> x, 8 -> x, 4 -> x) 

scala> t.take(2) 
res3: Traversable[Any] = Map(5 -> x, 10 -> x) 

एक unoptimized मानचित्र रिटर्न यही कारण है कि, उदाहरण के लिए:

scala> res3.getClass 
res4: Class[_ <: Traversable[Any]] = class scala.collection.immutable.HashMap$HashTrieMap 

scala> Map(1->"x",2->"x").getClass 
res5: Class[_ <: scala.collection.immutable.Map[Int,String]] = class scala.collection.immutable.Map$Map2