将String拆分为具有特定长度的组

时间:2022-01-01 01:59:36

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

如何将Swift中给定的String拆分为给定长度的组,从右到左阅读?

For example, I have string 123456789 and group length of 3. The the string should be divided into 3 groups: 123, 456, 789. String 1234567 will be divided into 1, 234, 567

例如,我有字符串123456789,组长度为3.字符串应分为3组:123,456,789。字符串1234567将分为1,234,567

So, can you write some nice code in Swift:

那么,你能在Swift中编写一些不错的代码吗:

func splitedString(string: String, length: Int) -> [String] {

}

BTW tried function split(), but as I understand it works only with finding some symbol

BTW尝试了函数split(),但据我所知它只能找到一些符号

8 个解决方案

#1


2  

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

只是为了加入这个非常拥挤的比赛(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]
        }
}

#2


1  

This is what I came up with off the top of my head. I bet there is a better way of doing it so I'd encourage you to keep trying.

这就是我想到的最重要的事情。我打赌有更好的方法,所以我鼓励你继续努力。

func splitedString(string: String, length: Int) -> [String] {
    var groups = [String]()
    var currentGroup = ""
    for index in string.startIndex..<string.endIndex {
        currentGroup.append(string[index])
        if currentGroup.characters.count == 3 {
            groups.append(currentGroup)
            currentGroup = ""
        }
    }

    if currentGroup.characters.count > 0 {
        groups.append(currentGroup)
    }

    return groups
}

Here were my tests

这是我的测试

let firstString = "123456789"
let groups = splitedString(firstString, length: 3)
// Returned ["123", "456", "789"]

let secondString = "1234567"
let moreGroups = splitedString(secondString, length: 3)
// Returned ["123", "456", "7"]

#3


1  

Here is a version using NSRegularExpressions

这是一个使用NSRegularExpressions的版本

func splitedString(string: String, length: Int) -> [String] {
    var groups = [String]()
    let regexString = "(\\d{1,\(length)})"
    do {
        let regex = try NSRegularExpression(pattern: regexString, options: .CaseInsensitive)
        let matches = regex.matchesInString(string, options: .ReportCompletion, range: NSMakeRange(0, string.characters.count))
        let nsstring = string as NSString
        matches.forEach {
            let group = nsstring.substringWithRange($0.range) as String
            groups.append(group)
        }
    } catch let error as NSError {
        print("Bad Regex Format = \(error)")
    }

    return groups
}

#4


1  

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)

#5


1  

Swift 4

斯威夫特4

I think the extension method is more useful.

我认为扩展方法更有用。

extension String{

    public func splitedBy(length: Int) -> [String] {

        var result = [String]()

        for i in stride(from: 0, to: self.characters.count, by: length) {
            let endIndex = self.index(self.endIndex, offsetBy: -i)
            let startIndex = self.index(endIndex, offsetBy: -length, limitedBy: self.startIndex) ?? self.startIndex
            result.append(String(self[startIndex..<endIndex]))
        }

        return result.reversed()

    }

}

the example of use:

使用示例:

Swift.debugPrint("123456789".splitedBy(length: 4))
// Returned ["1", "2345", "6789"]

#6


0  

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()
}

#7


0  

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"]

#8


0  

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

#1


2  

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

只是为了加入这个非常拥挤的比赛(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]
        }
}

#2


1  

This is what I came up with off the top of my head. I bet there is a better way of doing it so I'd encourage you to keep trying.

这就是我想到的最重要的事情。我打赌有更好的方法,所以我鼓励你继续努力。

func splitedString(string: String, length: Int) -> [String] {
    var groups = [String]()
    var currentGroup = ""
    for index in string.startIndex..<string.endIndex {
        currentGroup.append(string[index])
        if currentGroup.characters.count == 3 {
            groups.append(currentGroup)
            currentGroup = ""
        }
    }

    if currentGroup.characters.count > 0 {
        groups.append(currentGroup)
    }

    return groups
}

Here were my tests

这是我的测试

let firstString = "123456789"
let groups = splitedString(firstString, length: 3)
// Returned ["123", "456", "789"]

let secondString = "1234567"
let moreGroups = splitedString(secondString, length: 3)
// Returned ["123", "456", "7"]

#3


1  

Here is a version using NSRegularExpressions

这是一个使用NSRegularExpressions的版本

func splitedString(string: String, length: Int) -> [String] {
    var groups = [String]()
    let regexString = "(\\d{1,\(length)})"
    do {
        let regex = try NSRegularExpression(pattern: regexString, options: .CaseInsensitive)
        let matches = regex.matchesInString(string, options: .ReportCompletion, range: NSMakeRange(0, string.characters.count))
        let nsstring = string as NSString
        matches.forEach {
            let group = nsstring.substringWithRange($0.range) as String
            groups.append(group)
        }
    } catch let error as NSError {
        print("Bad Regex Format = \(error)")
    }

    return groups
}

#4


1  

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)

#5


1  

Swift 4

斯威夫特4

I think the extension method is more useful.

我认为扩展方法更有用。

extension String{

    public func splitedBy(length: Int) -> [String] {

        var result = [String]()

        for i in stride(from: 0, to: self.characters.count, by: length) {
            let endIndex = self.index(self.endIndex, offsetBy: -i)
            let startIndex = self.index(endIndex, offsetBy: -length, limitedBy: self.startIndex) ?? self.startIndex
            result.append(String(self[startIndex..<endIndex]))
        }

        return result.reversed()

    }

}

the example of use:

使用示例:

Swift.debugPrint("123456789".splitedBy(length: 4))
// Returned ["1", "2345", "6789"]

#6


0  

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()
}

#7


0  

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"]

#8


0  

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