2011-08-14 11 views
10

मेरा एक दोस्त के लिए कार्यात्मक शैली स्काला सबसे लंबे समय तक लाइन का ट्रैक एक फाइल में रखने के लिए सीख रहा है और लिखा है इस सरल कोड: बहुत स्काला के लिए नएइस स्काला कोड

val longest = (filename:String) => { 
    val is = new FileInputStream(filename) 
    val buf = new Array[Byte](1024) 
    var longest=0 //keep track of the longest line 
    var lastPos=0 
    var read=0 
    try { 
    read = is.read(buf) 
    while (read > 0) { 
     for (i<-0 until read) { 
     if (buf(i) == '\n') { 
      val size=i-lastPos-1 
      lastPos=i 
      if (size>longest) { 
      longest=size 
      } 
     } 
     } 
     lastPos-=buf.length 
     read=is.read(buf) 
    } 
    } finally { 
    is.close() 
    } 
    longest 
} 

मैं हूँ, लेकिन मैं ' मुझे यकीन है कि इस कोड में flatMaps और अन्य कार्यों के लिए बहुत सी जगह है।

क्या कोई इस का कार्यात्मक संस्करण पोस्ट कर सकता है?

उत्तर

5

हां, यह कोड दर्दनाक रूप से अनिवार्य है। स्काला में किसी न किसी तरह बराबर होगा (!):

def longest(fileName: String) = 
    Source.fromFile(fileName).getLines().max(Ordering.fromLessThan[String](_.size < _.size)).size 

लगता यह कुछ स्पष्टीकरण प्रदान करने के लिए चोट नहीं होगा:

def longest(fileName: String) = Source. 
    fromFile(fileName).  //file contents abstraction 
    getLines().  //iterator over lines 
    max(  //find the max element in iterated elements 
     Ordering.fromLessThan[String](_.size < _.size) //however, use custom comparator by line size 
    ).size //max() will return the line, we want the line length 
पाठ्यक्रम TMTOWTDI के स्काला में

13
val longest = (filename: String) => 
    io.Source.fromFile(filename).getLines.maxBy(_.length).length 
+0

मान्य रूप से 'maxBy' के साथ आपका समाधान मेरा, +1 से अधिक सुखद है। –

+0

हैलो @ missingfaktor यह अधिक कुशल दिखता है नहीं है? मैं समझता हूं कि यह लाइनों को पढ़ने के दौरान '_.length' कोड लागू होता है लेकिन मुझे नहीं लगता कि यह अधिकतम की बजाय "लंबाई" क्यों देता है, यह नहीं होना चाहिए ... minby (_। Length) [0 ] 'या ऐसा कुछ? – OscarRyz

+0

@ ऑस्कर: बेन का कोड उतना तेज़ होना चाहिए (दिया गया है कि 'गेटलाइन' एक पुनरावर्तक लौटाता है)। – missingfaktor

24

एक वैकल्पिक कार्यान्वयन:

def longest(filename: String) = 
    Source.fromFile(filename).getLines.map(_.size).max 

संक्षिप्त विवरण:

  • getLines फ़ाइल की पंक्तियों का एक iterator देता है;
  • map(_.size), map(line => line.size) के बराबर है, रिटर्न लाइन का एक नया इटरेटर लंबाई
  • max रिटर्न सबसे बड़ी लाइन की लंबाई।
+0

यह कोड कितना कुशल है। मैं "अनुमान लगा सकता हूं" यह फ़ाइल को पुन: सक्रिय करता है (या इसे स्मृति में रखता है) तीन बार, गेटलाइन के लिए 1, मानचित्र के लिए 1, और अधिकतम प्राप्त करने के लिए अंतिम, जबकि मूल कोड केवल एक पास होता है, लेकिन मैं गलत हो सकता हूं पाठ्यक्रम। – OscarRyz

+4

फ़ाइल केवल एक बार फिर से शुरू की जाएगी। जब आप 'मानचित्र' कहते हैं, तो यह इटरेटर से कोई भी मूल्य नहीं खींचता है; यह '_.size' फ़ंक्शन को संग्रहीत करता है और एक नया इटरेटर बनाता है जो उस फ़ंक्शन को पहले इटरेटर * के प्रत्येक आउटपुट पर लागू करेगा * जब कॉल किया जाता है *। 'अधिकतम' को कॉल करने से अंततः पुनरावृत्ति को बल दिया जाता है। –

+0

समझ गया, यही कारण है कि इसे 'बुफर्डसोर्स' कहा जाता है :) '.max' के बारे में क्या? – OscarRyz