Count the number of lines in a Swift String

后端 未结 3 1150
天涯浪人
天涯浪人 2021-01-14 10:15

After reading a medium sized file (about 500kByte) from a web-service I have a regular Swift String (lines) originally encoded in .isolatin1. Befor

相关标签:
3条回答
  • 2021-01-14 10:39

    As I did not find a generic way to count newlines I ended up just solving my problem by iterating through all the characters using

    let linesCount = text.reduce(into: 0) { (count, letter) in
         if letter == "\r\n" {      // This treats CRLF as one "letter", contrary to UnicodeScalars
            count += 1
         }
    }
    

    I was sure this would be a lot faster than enumerating lines for just counting, but I resolved to eventually do the measurement. Today I finally got to it and found ... that I could not have been more wrong.

    A 10000 line string counted lines as above in about 1.0 seconds , but counting through enumeration using

    var enumCount = 0
    text.enumerateLines { (str, _) in
        enumCount += 1
    }
    

    only took around 0.8 seconds and was consistently faster by a little more than 20%. I do not know what tricks the Swift engineers hide in their sleves, but they sure manage to enumerateLines very quickly. This just for the record.

    0 讨论(0)
  • 2021-01-14 10:40

    If it's ok for you to use a Foundation method on an NSString, I suggest using

    enumerateLines(_ block: @escaping (String, UnsafeMutablePointer<ObjCBool>) -> Void)
    

    Here's an example:

    import Foundation
    
    let base = "Hello, playground\r\nhere too\r\nGalahad\r\n"
    let ns = base as NSString
    
    ns.enumerateLines { (str, _) in
        print(str)
    }
    

    It separates the lines properly, taking into account all linefeed types, such as "\r\n", "\n", etc:

    Hello, playground
    here too
    Galahad

    In my example I print the lines but it's trivial to count them instead, as you need to - my version is just for the demonstration.

    0 讨论(0)
  • 2021-01-14 10:56

    Swift 5 Extension

    extension String {
        
        func numberOfLines() -> Int {
            return self.numberOfOccurrencesOf(string: "\n") + 1
        }
        
    }
    

    Example:

    let testString = "First line\nSecond line\nThird line"
    let numberOfLines = testString.numberOfLines() // returns 3
    
    0 讨论(0)
提交回复
热议问题