स्काला वाट: संग्रह

पिछली बार हमने वैकल्पिक मानों का प्रसंस्करण किया था, यह पता चला कि स्काला लाइब्रेरी के सुरुचिपूर्ण उपकरणों का गलत तरीके से उपयोग करके, आप पैरों में अपने आप को शूट करना जारी रख सकते हैं।

इस बार चलिए संग्रह पर चलते हैं। स्काला संग्रह मानक पुस्तकालय इतना समृद्ध है कि यह सबसे अधिक मांग वाले डेवलपर्स के लिए भी तैयार किए गए तरीकों की पेशकश कर सकता है। किन मामलों में आमतौर पर इसका वर्णन नहीं किया जाता है कि किन तरीकों को लागू किया जाए और सब कुछ अनुभव से सीखा जाए। आमतौर पर, शुरुआत में हर कोई filter और map को पहचान लेगा, यह इस तक सीमित हो सकता है, क्योंकि एक निश्चित फंतासी के साथ आप इन कार्यों पर केवल कई एल्गोरिदम लागू कर सकते हैं। हालांकि, ये विधियां इष्टतम नहीं हो सकती हैं या डोमेन के लिए असंभव परिणाम उत्पन्न कर सकती हैं, जिन्हें, हालांकि, संसाधित करना होगा।

नीचे हम चर्चा करेंगे कि मानक पुस्तकालय की कौन सी विशेषताएं अक्सर गलत तरीके से उपयोग की जाती हैं और क्या सुधार किया जा सकता है।

foreach और for (val i = 0; मैं <n; i ++)


स्काला में स्विच करते समय, for(;;) की कमी के कारण कई लोग टूट जाते हैं। कोई, विशेषकर जिन्होंने C में लिखा है, का मानना ​​है कि इस तरह के चक्र के बिना कार्यक्रमों को लिखना असंभव है, अधिक उन्नत लोगों ने प्रारंभिक परिस्थितियों को हटाने और बाहरी कोड में चक्र के कदम के साथ एनालॉग्स लिखने की कोशिश की, उदाहरण के लिए:

 var i = 0 //  var! while(i < n) { //  - ,   i i = i+1 } 

वास्तव में, for(val i = 0; i< n; i++) के for(i <- 0 until n) सबसे सटीक एनालॉग है for(i <- 0 until n) ;
इसलिए यहां सब कुछ सतह पर था, हालांकि यह अभी तुरंत दिखाई नहीं देता है। सही तरीके से लिखने के लिए, आपको श्रेणी वर्ग के संचालन को जानना होगा और ब्लॉग पर इसके उपयोग के उदाहरणों को देखना होगा, जैसे कि कोड कमिट

इटरेटर


अक्सर, पुराने जावा कोड के साथ काम करते समय, कक्षाएं आती हैं जो सामान्य रूप से पुनरावृत्त नहीं हो सकती हैं। उदाहरण के रूप में java.sql.ResultSet को लें ( Enumeration भी रोल करती है)। यह Iterable नहीं है, अर्थात, इसके लिए JavaConversions का कोई पारदर्शी रूपांतरण नहीं है, और आपको इसके साथ विशेष रूप से अनिवार्य रूप से काम करना होगा या इसे एक मध्यवर्ती उत्परिवर्तित संग्रह की सामग्री में कॉपी करना होगा, एक विकल्प के रूप में, बिल्डर के माध्यम से उपयोग करने योग्य बनाना होगा। डरावना।

इस मामले के लिए, स्काला स्टैण्डर्ड लाइब्रेरी में एक Iterator वर्ग होता है जो आपको ResultSet से एक खाद्य Iterator बनाने की अनुमति देता है, जो कम से कम Traversable :

 val resultSetIterator = Iterator.continually(resultSet).takeWhile(_.next()) 

सरल प्रतिस्थापन और द्विआधारी तर्क


आइए सरल प्रतिस्थापन नियमों से शुरू करें जब कॉल श्रृंखला को सरल या यहां तक ​​कि एक सरल विधि से बदला जा सकता है। सबसे आसान तरीके जो आपकी मदद कर सकते हैं वे exists , forall और find । मैंने अक्सर देखा:

 option.map(myValueIsGoodEnough).getOrElse(false) 

बजाय
 option.exists(goodEnoughValue) //   `option exists goodEnoughValue` 

तो
 iterable.filter(goodEnough).headOption 

बजाय
 iterable.find(goodEnough) 

यह भी हुआ (हालांकि, हमारे कोड में सही है!)
 iterable.foldLeft(true)(_ && goodEnough) 

के बजाय
 iterable.forall(goodEnough) 

कहने की जरूरत नहीं है, सरल विकल्प न केवल पढ़ने के लिए सरल हैं, बल्कि अधिक कुशलता से लागू किए गए हैं, क्योंकि map , filter और foldLeft पूरे संग्रह की जांच करेगा चाहे वह कितना भी लंबा हो, जबकि exists , find और forall जैसे ही उन्हें एक उपयुक्त (या अनुचित) तत्व मिलेगा तुरंत समाप्त हो जाएगा और एक अतिरिक्त मध्यवर्ती संग्रह उत्पन्न नहीं करेगा।

Coursera.com पर स्काला कोर्स dropWhile कई उपयोगी विशेषताएं dropWhile कीं: span , dropWhile और takeWhile । उनका उपयोग करना भी व्यवहार में स्पष्ट नहीं हो सकता है, क्योंकि filter सफलतापूर्वक इन मामलों के लिए भी काम करता है, हालांकि कम कुशलता से, क्योंकि वह नहीं जानता है कि किसी भी क्षण से तत्वों को जांचने की आवश्यकता नहीं है: वे सभी पहले से ही फिट हैं या फिट नहीं हैं। उदाहरण के लिए, हाल ही में, मैंने स्वयं विनिमय दरों के अनुक्रम की शुरुआत और अंत को साफ किया, जो अंतराल में नहीं हैं, filter माध्यम से, और dropWhile और takeWhile माध्यम से नहीं।

समुच्चय


fold , foldLeft और foldRight बहुत शक्तिशाली हैं और इनका उपयोग पूरी तरह से अलग-अलग समस्याओं को हल करने के लिए किया जा सकता है।
उदाहरण के लिए, foldLeft पर हमें रहने दें, इसकी सहायता से आप संग्रह के तत्वों का योग प्राप्त कर सकते हैं:

 iterable.foldLeft(0) { (accum, elem) => accum + elem } 

ऐसे कोड के लिए विहित वर्तनी निम्नानुसार है:

 iterable.foldLeft(0) { _ + _ } 

इसके लिए मार्टिन ओडस्की ने स्काला डेज़ पर एक दिलचस्प विकल्प दिखाया:

 (0 /: iterable)(_ + _) 

कहते हैं, जैसे कि डोमिनोज़ बाएं से दाएं गिरते हैं :) प्लस को यहां अधिक विस्तार से वर्णित किया गया है , लेकिन मैं अभी भी प्रतीकात्मक ऑपरेटरों पर संदेह कर रहा हूं यदि वे विषय क्षेत्र के लिए अच्छी तरह से ज्ञात नहीं हैं।

किसी भी स्थिति में, इस स्थिति में, आपको यह कोड नहीं लिखना चाहिए, क्योंकि टाइपकास्ट Numeric तत्वों के साथ संग्रह के लिए एक विशेष विधि है, आप और अधिक सरल रूप से लिख सकते हैं:

 iterable.sum 

min और max कार्य भी उपलब्ध हैं (विशेष शिल्पकार संग्रह को छांटना और सिर / पूंछ लेना पसंद करते हैं, मुझे यह अच्छी तरह से दिखाई नहीं देता है)।

उच्च स्तरीय एल्गोरिथ्म के एक के बाद एक आवेदन करने के लिए तह लगाने के तरीकों को बचाना बेहतर है, उदाहरण के लिए, चेन-ऑफ-जिम्मेदारी में या अपने मैप-कम में कम करें।

कभी-कभी प्रसंस्करण ग्राफ़ और समय के साथ वितरित सामान्य जानकारी में, आपको जोड़े (वर्तमान और पिछले) में तत्वों को संसाधित करना पड़ता है, इस मामले में आप वास्तव में चाहते हो सकते हैं, मैं for(;;) लिए उपयोग करना चाहता था और सूचकांकों के साथ खेलना चाहता था।

 for(i <- 1 until seq.size) { result ++= combine(seq(i-1), seq(i)) } 

स्काला में, आप एक अनुक्रम को एक तत्व द्वारा स्थानांतरित कर सकते हैं और फिर एक फ़ंक्शन लागू कर सकते हैं जो दोनों तत्वों को संसाधित करता है:

 seq.zip(seq.drop(1)).map(combine) //    list.zip(list.tail).map(combine) // ,     

बस यह जांचना याद रखें कि शीट खाली नहीं है!

उसी कोड को लिखना अधिक सही है

 seq.sliding(2).map(calculateDelta) 


और अब अच्छी खबर है, JavaOne पर यह बहुत सारे सरलीकरणों को इंटेलीज से लोगों को पंजीकृत करने के लिए निकला, और पहले ही स्काला डेज़ द्वारा वे उन्हें लागू करने में कामयाब रहे और कई और



दोस्तों अब स्काला निरीक्षण में एक विशेष व्यक्ति शामिल है, इसलिए यदि आपके पास सरलीकरण पर कोई दिलचस्प विचार है - टिकट बनाएं , सब कुछ होगा!

एक अच्छा कोड लिखें और खुश रहें।

Source: https://habr.com/ru/post/In184310/


All Articles