2010-04-03 15 views
5

संपादित करें: इस तथ्य को जोड़ा गया है कि सूची क्रमबद्ध है, और 'डुप्लिकेट' को समझना भ्रामक है, इसे शीर्षक में 'अनावश्यक' के साथ बदल दिया गया है।अनावश्यक प्रविष्टियों को हटाएं, स्कैला रास्ता

मेरे पास किसी दिए गए अंतराल में उत्पादन मूल्य बताते हुए प्रविष्टियों की एक क्रमबद्ध सूची है। बाद में सटीक समान मूल्य बताते हुए प्रविष्टियां कोई जानकारी नहीं जोड़ती हैं और सुरक्षित रूप से छोड़ी जा सकती हैं।

case class Entry(minute:Int, production:Double) 
val entries = List(Entry(0, 100.0), Entry(5, 100.0), Entry(10, 100.0), Entry(20, 120.0), Entry(30, 100.0), Entry(180, 0.0)) 

, साथ स्केला 2.8 संग्रह कार्यों प्रयोग अब तक मैं इस काम कर कार्यान्वयन है:

entries.foldRight(List[Entry]()) { 
    (entry, list) => list match { 
    case head :: tail if (entry.production == head.production) => entry :: tail 
    case head :: tail => entry :: list 
    case List() => entry :: List() 
    } 
} 
res0: List[Entry] = List(Entry(0,100.0), Entry(20,120.0), Entry(30,100.0), Entry(180,0.0)) 

कोई टिप्पणी? क्या मैं कुछ स्कैला जादू पर लापता हूं?

+0

आपको याद है, 'फ़ोल्ड राइट' 'सूची' के साथ उप-शीर्ष है। इसके साथ 'foldLeft' पसंद करें।यह 'हास्केल' के विपरीत है, जहां गैर-कठोरता के कारण 'बाएं' पर 'राइट' को प्राथमिकता दी जाती है। –

+0

ठीक है, लेकिन फिर मुझे परिणाम को उलट करने की आवश्यकता है। एक त्वरित परीक्षण चलाना foldRight + reverse से थोड़ी आगे आगे बढ़ता है, तो मैं कहूंगा कि foldRight स्पष्ट है। – andersbohn

उत्तर

9

जब आप किसी सूची में लगातार प्रविष्टियों की तुलना कर रहे हैं, तो zip से शुरू करें- अपनी पूंछ के साथ सूची को लगातार तत्वों के जोड़े की सूची प्राप्त करने के लिए शुरू करें।

नीचे, मैं सूची से पहली प्रविष्टि लेता हूं, और collect का उपयोग उन जोड़ों को फ़िल्टर करने के लिए करता हूं जहां उत्पादन अपरिवर्तित होता है, और शेष जोड़े के लिए, मानचित्र e2। (collect स्काला 2.8 में नया है, और थोड़ी देर के लिए partialMap बुलाया गया था)

scala> entries.head :: ((entries zip entries.tail).collect { 
      case (Entry(_, p1), [email protected](_, p2)) if p1 != p2 => e2 
     }) 
res13: List[Entry] = List(Entry(0,100.0), Entry(20,120.0), Entry(30,100.0), Entry(180,0.0)) 

अद्यतन सादगी के लिए, यह मानता है कि प्रविष्टियों खाली नहीं है।

+1

पूंछ के साथ ज़िप, बहुत अच्छा सामान्य विचार। यह ठीक से थोड़ा धीमा है। x2 मेरे सेटअप पर (2.8.0.बीटा 1-आरसी 3, जहां संग्रह अभी भी 'आंशिक मैप' है, डुनो अगर यह प्रदर्शन को प्रभावित करता है) – andersbohn

+1

@andersbohn आप बेहतर प्रदर्शन प्राप्त करने के लिए 'प्रविष्टियों .view ज़िप प्रविष्टियों.tail' का उपयोग कर सकते हैं (अंत में 'toList'), लेकिन मेरे परीक्षणों ने आपके संस्करण को 30 पर रखा,' व्यू '63 पर और 81 का नाम बदल गया। –

0

प्रत्येक आइटम के लिए डुप्लिकेट की तलाश करने के बजाय, ओ (एन^2), या ज़िपिंग, जो स्मृति में n^2 है, मानचित्र [डबल, Int] का उपयोग करें। फिर केवल 'उत्पादन' के साथ आइटम को कुंजी के रूप में कुंजी और 'मिनट' के रूप में जोड़ें। नक्शा 'उत्पादन' के लिए अद्वितीय मूल्य सुनिश्चित करेगा। आप अपने कोड में स्वाभाविक रूप से कहीं और नक्शा लोड करने में सक्षम हो सकते हैं, लेकिन यदि आपको ऊपर की सूची के साथ शुरू करना है, तो मानचित्र को लोड करना सूची में रैखिक है और केवल मानचित्र पर ओ (एन लॉग (एन)) है।

नक्शा बदल जाएगा क्योंकि आप "mymap + = production -> minute" जोड़ते हैं ताकि पहले मान को बनाए रखने के लिए, 'शामिल (कुंजी)' गार्ड डालने या उपयोग करने से पहले सूची को उलट दें। चेक ओ (लॉग (एन)) होगा, इसलिए कुल मिलाकर एल्गोरिदम ओ (एन लॉग (एन)) होगा।

बीटीडब्लू, आप उत्पादन मूल्यों से सीधे अपने एंट्री संरचनाओं में मानचित्र के लिए मानचित्र [डबल, एंट्री] का उपयोग कर सकते हैं। फिर मानचित्र की कीमतों को सीधे नक्शे से खींचकर और प्रविष्टि के तत्व (अगर आवश्यक हो) पर सॉर्ट करके, यदि आवश्यक हो, तो आप आसानी से एक सूची प्राप्त कर सकते हैं।

+0

मुझे लगता है कि आप गलत पढ़ रहे हैं। एंडर्सबोहन को केवल सूची के माध्यम से जाना होगा; यह पहले से ही क्रमबद्ध है, और यदि कोई उत्पादन आता है, परिवर्तन करता है, और फिर वापस बदल जाता है, तो आपको _do_ को नए उत्पादन की आवश्यकता होती है। (बिंदु केवल कुछ भी फेंकना है जो आप पहले से ही अनावश्यक के रूप में कर रहे हैं।) दोनों शब्दकोष के कोड और एंडर्सबॉन 'ओ (एन)' हैं; वे डेटा के माध्यम से एक बार गुजरते हैं। –

+0

शायद; मुझे नहीं लगता कि मूल प्रश्न इतना विशिष्ट था। उम्मीद है कि मेरा जवाब इसी तरह के सवालों के साथ दूसरों के लिए सहायक होगा। साथ ही, आइटम की संख्या में प्रत्येक बार एल्गोरिदम ओ (एन^2) को पूरी सूची खोजना। इसे हैशटेबल या वृक्ष संरचना के साथ बेहतर किया जा सकता है। – DrGary

+0

यदि आपने ओ (लॉग एन) अपडेट के बारे में कुछ कहा था, तो शायद मैं सहमत हूं। अन्यथा, जब आप ओ (एन लॉग एन) में सॉर्ट कर सकते हैं तो मानचित्र का उपयोग क्यों करें और फिर ओ (एन) में डुप्लिकेट हटा दें? –

3

विधि Tuple2 के साथ विधि है जो zip से कुछ परिचालनों के लिए सूचियों पर अधिक कुशल (और आलसी) है। आप अपने बेंचमार्क पर इस बाहर की कोशिश कर सकते हैं - यदि यह वास्तव में तेज है मैं नहीं जानता, लेकिन यह निश्चित हो सकता है (और यह निश्चित रूप से एक बहुत छोटा है):

entries.take(1) ::: 
(entries,entries.drop(1)).zipped.filter(_.production != _.production)._2 

के बजाय सभी सूची जोड़ो में ज़िप करने जिस तरह से, यह सूची का एक दृश्य बनाता है जहां टुकड़ों को एक साथ जोड़ दिया जा सकता है, और उसके बाद छेड़छाड़ की सूचियां लौटाती हैं। रिक्त मामले को संभालने के लिए लेने और ड्रॉप के उपयोग पर ध्यान दें।

यह सुपर-कुशल नहीं है क्योंकि यह वास्तव में केवल एक की आवश्यकता होने पर दो सूचियां बनाता है, लेकिन यह समाधान का एक वर्ग है जो अभी तक नहीं आया है।

संबंधित मुद्दे