Split String into groups with specific length

后端 未结 10 1772
囚心锁ツ
囚心锁ツ 2021-01-05 09:32

How can I split the given String in Swift into groups with given length, reading from right to left?

For example, I have string 123456789 a

相关标签:
10条回答
  • 2021-01-05 09:59

    Another solution using substrings:

    func splitStringByIntervals(str: String, interval: Int) -> [String] {
    
       let st = String(str.characters.reverse())
       let length = st.characters.count  
       var groups = [String]()
    
       for (var i = 0; i < length; i += interval) {
           groups.append((st as NSString).substringWithRange(NSRange(location: i, length: min(interval, length - i))))
       }
    
       return groups.map{ String($0.characters.reverse())}.reverse()
    }
    

    The output for :

    for element in splitStringByIntervals("1234567", interval: 3) {
       print(element)
    }
    

    is:

    1
    234
    567
    
    0 讨论(0)
  • 2021-01-05 10:00

    I made something like this, couldn't create anything better looking, but its result matches the question:

    func splitedString(string: String, lenght: Int) -> [String] {
        var result = [String](), count = 0, line = ""
        for c in string.characters.reverse() {
            count++; line.append(c)
            if count == lenght {count = 0; result.append(String(line.characters.reverse())); line = ""}
        }
        if !line.isEmpty {result.append(String(line.characters.reverse()))}
        return result.reverse()
    }
    
    0 讨论(0)
  • 2021-01-05 10:04

    Just to add my entry to this very crowded contest (SwiftStub):

    func splitedString(string: String, length: Int) -> [String] {
        var result = [String]()
    
        for var i = 0; i < string.characters.count; i += length {
            let endIndex = string.endIndex.advancedBy(-i)
            let startIndex = endIndex.advancedBy(-length, limit: string.startIndex)
            result.append(string[startIndex..<endIndex])
        }
    
        return result.reverse()
    }
    

    Or if you are feeling functional-y:

    func splitedString2(string: String, length: Int) -> [String] {
        return 0.stride(to: string.characters.count, by: length)
            .reverse()
            .map {
                i -> String in
                let endIndex = string.endIndex.advancedBy(-i)
                let startIndex = endIndex.advancedBy(-length, limit: string.startIndex)
                return string[startIndex..<endIndex]
            }
    }
    
    0 讨论(0)
  • 2021-01-05 10:06

    There's probably a more elegant solution, but this works:

    func splitedString(string: String, length: Int) -> [String] {
        let string = Array(string.characters)
        let firstGroupLength = string.count % length
        var result: [String] = []
        var group = ""
    
        if firstGroupLength > 0 {
            for i in 0..<firstGroupLength {
                group.append(string[i])
            }
            result.append(String(group))
            group = ""
        }
    
        for i in firstGroupLength..<string.count {
            group.append(string[i])
            if group.characters.count == length {
                result.append(group)
                group = ""
            }
        }
        return result
    }
    
    splitedString("abcdefg", length: 2) // ["a", "bc", "de", "fg"]
    splitedString("1234567", length: 3) // ["1", "234", "567"]
    
    0 讨论(0)
  • 2021-01-05 10:10
    func split(every length:Int) -> [Substring] {
        guard length > 0 && length < count else { return [suffix(from:startIndex)] }
    
        return (0 ... (count - 1) / length).map { dropFirst($0 * length).prefix(length) }
    }
    
    func split(backwardsEvery length:Int) -> [Substring] {
        guard length > 0 && length < count else { return [suffix(from:startIndex)] }
    
        return (0 ... (count - 1) / length).map { dropLast($0 * length).suffix(length) }.reversed()
    }
    

    Tests:

        XCTAssertEqual("0123456789".split(every:2), ["01", "23", "45", "67", "89"])
        XCTAssertEqual("0123456789".split(backwardsEvery:2), ["01", "23", "45", "67", "89"])
        XCTAssertEqual("0123456789".split(every:3), ["012", "345", "678", "9"])
        XCTAssertEqual("0123456789".split(backwardsEvery:3), ["0", "123", "456", "789"])
        XCTAssertEqual("0123456789".split(every:4), ["0123", "4567", "89"])
        XCTAssertEqual("0123456789".split(backwardsEvery:4), ["01", "2345", "6789"])
    
    0 讨论(0)
  • 2021-01-05 10:10

    Here's an another version with Functional Programming.

    extension String{
        func splitedString(length: Int) -> [String]{
            guard length > 0 else { return [] }
            let range = 0..<((characters.count+length-1)/length)
            let indices = range.map{ length*$0..<min(length*($0+1),characters.count) }
            return indices
                    .map{ characters.reverse()[$0.startIndex..<$0.endIndex] }
                    .map( String.init )
        }
    }
    
    "1234567890".splitedString(3)
    
    0 讨论(0)
提交回复
热议问题