उदाहरण के लिए मुद्रित करने के लिए अंतिम पंक्तिक्या लूप के लिए स्कैला में अंतिम मामले को अलग-अलग संभालने का कोई तरीका है?
println("}")
उदाहरण के लिए मुद्रित करने के लिए अंतिम पंक्तिक्या लूप के लिए स्कैला में अंतिम मामले को अलग-अलग संभालने का कोई तरीका है?
println("}")
मिलान पैटर्न का उपयोग कर सकते हैं एक अनुशंसा में println
से बचने की सलाह देते हैं। यह कभी-कभी किसी संग्रह के बीच में होने वाली बग को ट्रैक करने के लिए उपयोगी हो सकता है, लेकिन अन्यथा कोड को ले जाता है जो रिफैक्टर और परीक्षण करना कठिन होता है।
अधिक आम तौर पर, जीवन आमतौर पर आसान हो जाता है यदि आप को साइड-इफेक्ट के प्रकार को प्रतिबंधित कर सकते हैं। तो बजाय:
for (line <- myData) {
println("}, {")
}
आप लिख सकते हैं:
val lines = for (line <- myData) yield "}, {"
println(lines mkString "\n")
मैं भी यहाँ एक अनुमान लेने के लिए है कि आप उत्पादन में प्रत्येक पंक्ति की सामग्री चाहते थे जा रहा हूँ!
val lines = for (line <- myData) yield (line + "}, {")
println(lines mkString "\n")
हालांकि अगर आप सिर्फ सीधे mkString
इस्तेमाल किया आप अभी भी बेहतर होगा - कि क्या इसके लिए है!
val lines = myData.mkString("{", "\n}, {", "}")
println(lines)
नोट कैसे हम पहली बार एक String
उत्पादन कर रहे हैं, फिर एक ही आपरेशन में यह मुद्रण। इस दृष्टिकोण को आसानी से अलग-अलग तरीकों से विभाजित किया जा सकता है और आपकी कक्षा में toString
लागू करने के लिए या परीक्षण में उत्पन्न स्ट्रिंग का निरीक्षण करने के लिए उपयोग किया जा सकता है।
आप एक उदाहरण के रूप TraversableOnce
विशेषता के addString समारोह का समय लग सकता लगता है मुझे
for (line <- myData) {
println("}, {")
}
पाने के लिए एक रास्ता है नहीं है।
def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = {
var first = true
b append start
for (x <- self) {
if (first) {
b append x
first = false
} else {
b append sep
b append x
}
}
b append end
b
}
आपके मामले में, विभाजक }, {
है और अंत }
+1 का उपयोग करने के लिए –
आप का लाभ लेने के लिए अपने कोड refactor कर सकते हैं है निर्मित mkString
?
scala> List(1, 2, 3).mkString("{", "}, {", "}")
res1: String = {1}, {2}, {3}
आप में निर्मित mkString समारोह का उपयोग नहीं करना चाहते, तो आप कर सकते हैं की तरह
for (line <- lines)
if (line == lines.last) println("last")
else println(line)
अद्यतन कुछ:didierd टिप्पणी में उल्लेख किया है, इस समाधान क्योंकि अंतिम मान गलत है कई बार हो सकता है, वह अपने answer में बेहतर समाधान प्रदान करता है।
क्योंकि last
समारोह "प्रभावी ढंग से निरंतर समय" उनके लिए Lists
के लिए के रूप में लेता है, यह Vectors
के लिए ठीक है, यह रेखीय समय लगता है,, मैं तो तुम आगे किसी भी जाने से पहले
@tailrec
def printLines[A](l: List[A]) {
l match {
case Nil =>
case x :: Nil => println("last")
case x :: xs => println(x); printLines(xs)
}
}
रिकर्सिव समाधान ठीक है। == lines.last वाला एक गलत है जब तक कि आपको पता न हो कि अंतिम तत्व का मान कहीं और नहीं होता है। –
@didierd धन्यवाद, मुझे याद आया। मैंने जवाब में गलती की ओर इशारा किया। – 4e6
मैंने '==' के बजाय 'eq' का उपयोग करके इसे आजमाया और यह अभी भी काम नहीं करता है - स्ट्रिंग्स को कैश किया जाना चाहिए, जो दर्द का थोड़ा सा दर्द है –
मैं mkstring
का उपयोग करने से पहले जो कहा गया है उससे पहले पूरी तरह सहमत हूं, और पिछले एक के बजाय पहले पुनरावृत्ति को अलग करता हूं। क्या आपको अभी भी अंतिम पर अंतर करने की आवश्यकता होगी, स्कैला संग्रह में init
विधि है, जो सभी तत्वों को अंतिम रूप देता है लेकिन अंतिम। तो तुम
for(x <- coll.init) workOnNonLast(x)
workOnLast(coll.last)
(init
और last
सिर और पूंछ के विपरीत है, जो लेकिन पहले पहली और और सभी कर रहे हैं की जा रही है प्रकार) कर सकते हैं। हालांकि संरचना के आधार पर नोट, वे महंगा हो सकते हैं। Vector
पर, वे सभी तेज़ हैं। List
पर, जबकि सिर और पूंछ मूल रूप से मुक्त हैं, init
और last
दोनों सूची की लंबाई में रैखिक हैं। headOption
और lastOption
आपकी मदद कर सकती है जब संग्रह खाली हो सकता है, द्वारा
for (x <- coll.lastOption) workOnLast(x)
अन्य उत्तर हक mkString
की ओर इशारा कर रहे हैं workOnlast
की जगह है, और डेटा का एक सामान्य राशि के लिए मैं भी है कि प्रयोग करेंगे।
हालांकि, mkString
StringBuilder
के माध्यम से अंतिम परिणाम में स्मृति बनाता है (जमा करता है)। हमारे पास मौजूद डेटा की मात्रा के आधार पर यह हमेशा वांछनीय नहीं है।
इस मामले में, यदि हम चाहते हैं कि हम "प्रिंट" करना चाहते हैं तो हमें पहले बड़े परिणाम बनाने की आवश्यकता नहीं है (और शायद हम इससे भी बचना चाहते हैं)।
def forEachIsLast[A](iterator: Iterator[A])(operation: (A, Boolean) => Unit): Unit = {
while(iterator.hasNext) {
val element = iterator.next()
val isLast = !iterator.hasNext // if there is no "next", this is the last one
operation(element, isLast)
}
}
यह सभी तत्वों से अधिक iterates और operation
invokes एक बूलियन मान के साथ बदले में प्रत्येक तत्व गुजर,:
इस सहायक समारोह के कार्यान्वयन पर विचार करें। मान true
है यदि तत्व पारित किया गया है अंतिम एक है।
आपके मामले में इसे इस तरह इस्तेमाल किया जा सकता:
forEachIsLast(myData) { (line, isLast) =>
if(isLast)
println("}")
else
println("}, {")
}
हम यहाँ निम्न लाभ हैं:
या, थोड़ी अधिक सुंदरता से, शायद: 'प्रत्येक के लिए' बस 'वैल यह = seq हो सकता है।toIterator it.foreach {ऑपरेशन (_, it.hasNext)} ' –
बहुत बहुत धन्यवाद @TheAchechetypalPaul! आपके सुझाव के आधार पर एक कार्यान्वयन का उपयोग करने के लिए मेरा जवाब संपादित किया। –
@ निकोलस का उत्तर पहले ही इंगित करता है, यदि आप * वांछित * पुनरावृत्ति के लिए अलग-अलग कार्य करने के लिए अपने वांछित व्यवहार को दोबारा कर सकते हैं, तो यह अक्सर बहुत आसान होता है, आखिरी के बजाए। पहले पुनरावृत्ति की पहचान करना तुच्छ है। स्केल –
+1। यह देखने के लिए अच्छा है कि यह मानक पुस्तकालय में कैसे किया जाता है। –