将字符串拆分为特定长度的组
Split String into groups with specific length
如何将 Swift 中给定的 String
分成给定长度的组,从右到左阅读?
例如,我有字符串 123456789
和组长度为 3。字符串应分为 3 组:123
、456
、789
。字符串1234567
会被分成1
、234
、567
那么,你能不能在Swift中写一些漂亮的代码:
func splitedString(string: String, length: Int) -> [String] {
}
顺便说一句,尝试了函数 split()
,但据我所知,它只适用于找到一些符号
这是我突然想到的。我敢打赌有更好的方法,所以我鼓励您继续尝试。
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
}
这是我的测试
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"]
我做了这样的东西,无法创造出更好看的东西,但它的结果符合问题:
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()
}
这是一个使用 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([=10=].range) as String
groups.append(group)
}
} catch let error as NSError {
print("Bad Regex Format = \(error)")
}
return groups
}
这是另一个带有函数式编程的版本。
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*[=10=]..<min(length*([=10=]+1),characters.count) }
return indices
.map{ characters.reverse()[[=10=].startIndex..<[=10=].endIndex] }
.map( String.init )
}
}
"1234567890".splitedString(3)
可能有更优雅的解决方案,但这个可行:
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"]
另一个使用子字符串的解决方案:
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([=10=].characters.reverse())}.reverse()
}
输出:
for element in splitStringByIntervals("1234567", interval: 3) {
print(element)
}
是:
1
234
567
只是为了将我的条目添加到这个非常拥挤的比赛中 (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()
}
或者,如果您感觉功能正常:
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]
}
}
Swift 4
我觉得扩展方法更有用
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()
}
}
使用示例:
Swift.debugPrint("123456789".splitedBy(length: 4))
// Returned ["1", "2345", "6789"]
Swift 4
我调整了 以根据功能参数从左到右或从右到左操作,因此它更加通用。
extension String {
/// Splits a string into groups of `every` n characters, grouping from left-to-right by default. If `backwards` is true, right-to-left.
public func split(every: Int, backwards: Bool = false) -> [String] {
var result = [String]()
for i in stride(from: 0, to: self.count, by: every) {
switch backwards {
case true:
let endIndex = self.index(self.endIndex, offsetBy: -i)
let startIndex = self.index(endIndex, offsetBy: -every, limitedBy: self.startIndex) ?? self.startIndex
result.insert(String(self[startIndex..<endIndex]), at: 0)
case false:
let startIndex = self.index(self.startIndex, offsetBy: i)
let endIndex = self.index(startIndex, offsetBy: every, limitedBy: self.endIndex) ?? self.endIndex
result.append(String(self[startIndex..<endIndex]))
}
}
return result
}
}
示例:
"abcde".split(every: 2) // ["ab", "cd", "e"]
"abcde".split(every: 2, backwards: true) // ["a", "bc", "de"]
"abcde".split(every: 4) // ["abcd", "e"]
"abcde".split(every: 4, backwards: true) // ["a", "bcde"]
func split(every length:Int) -> [Substring] {
guard length > 0 && length < count else { return [suffix(from:startIndex)] }
return (0 ... (count - 1) / length).map { dropFirst([=10=] * 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([=10=] * length).suffix(length) }.reversed()
}
测试:
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"])
如何将 Swift 中给定的 String
分成给定长度的组,从右到左阅读?
例如,我有字符串 123456789
和组长度为 3。字符串应分为 3 组:123
、456
、789
。字符串1234567
会被分成1
、234
、567
那么,你能不能在Swift中写一些漂亮的代码:
func splitedString(string: String, length: Int) -> [String] {
}
顺便说一句,尝试了函数 split()
,但据我所知,它只适用于找到一些符号
这是我突然想到的。我敢打赌有更好的方法,所以我鼓励您继续尝试。
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
}
这是我的测试
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"]
我做了这样的东西,无法创造出更好看的东西,但它的结果符合问题:
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()
}
这是一个使用 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([=10=].range) as String
groups.append(group)
}
} catch let error as NSError {
print("Bad Regex Format = \(error)")
}
return groups
}
这是另一个带有函数式编程的版本。
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*[=10=]..<min(length*([=10=]+1),characters.count) }
return indices
.map{ characters.reverse()[[=10=].startIndex..<[=10=].endIndex] }
.map( String.init )
}
}
"1234567890".splitedString(3)
可能有更优雅的解决方案,但这个可行:
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"]
另一个使用子字符串的解决方案:
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([=10=].characters.reverse())}.reverse()
}
输出:
for element in splitStringByIntervals("1234567", interval: 3) {
print(element)
}
是:
1
234
567
只是为了将我的条目添加到这个非常拥挤的比赛中 (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()
}
或者,如果您感觉功能正常:
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]
}
}
Swift 4
我觉得扩展方法更有用
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()
}
}
使用示例:
Swift.debugPrint("123456789".splitedBy(length: 4))
// Returned ["1", "2345", "6789"]
Swift 4
我调整了
extension String {
/// Splits a string into groups of `every` n characters, grouping from left-to-right by default. If `backwards` is true, right-to-left.
public func split(every: Int, backwards: Bool = false) -> [String] {
var result = [String]()
for i in stride(from: 0, to: self.count, by: every) {
switch backwards {
case true:
let endIndex = self.index(self.endIndex, offsetBy: -i)
let startIndex = self.index(endIndex, offsetBy: -every, limitedBy: self.startIndex) ?? self.startIndex
result.insert(String(self[startIndex..<endIndex]), at: 0)
case false:
let startIndex = self.index(self.startIndex, offsetBy: i)
let endIndex = self.index(startIndex, offsetBy: every, limitedBy: self.endIndex) ?? self.endIndex
result.append(String(self[startIndex..<endIndex]))
}
}
return result
}
}
示例:
"abcde".split(every: 2) // ["ab", "cd", "e"]
"abcde".split(every: 2, backwards: true) // ["a", "bc", "de"]
"abcde".split(every: 4) // ["abcd", "e"]
"abcde".split(every: 4, backwards: true) // ["a", "bcde"]
func split(every length:Int) -> [Substring] {
guard length > 0 && length < count else { return [suffix(from:startIndex)] }
return (0 ... (count - 1) / length).map { dropFirst([=10=] * 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([=10=] * length).suffix(length) }.reversed()
}
测试:
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"])