String 如何将字符串拆分为等长的子字符串
所以 应该回来String 如何将字符串拆分为等长的子字符串,string,swift,swift2,String,Swift,Swift2,所以 应该回来 split("There are fourty-eight characters in this string", 20) 如果我设置currentIndex=string.startIndex,然后尝试将其向前推进(),使其超过string.endIndex,那么在检查currentIndex是否[字符串]{ 返回步幅(从:0到:self.count,按:长度)。映射{ let start=self.index(self.startIndex,offsetBy:$0) 让en
split("There are fourty-eight characters in this string", 20)
如果我设置currentIndex=string.startIndex,然后尝试将其向前推进(),使其超过string.endIndex,那么在检查currentIndex是否["There are fourty-eig", "ht characters in thi","s string"]
endIndex
不是有效的索引;它比有效范围多了一个。您不能使用超过字符串大小的范围。以下方法将演示如何执行此操作:
var string = "12345"
var currentIndex = string.startIndex
currentIndex = advance(currentIndex, 6)
if currentIndex > string.endIndex {currentIndex = string.endIndex}
或
“只需对字符序列执行一次操作,即可轻松解决此问题:
Swift 2.2
Swift 3.0
由于字符串是一种非常复杂的类型,范围和索引可能会根据视图的不同而有不同的计算成本。这些细节仍在不断发展,因此上述一次性解决方案可能是一种更安全的选择
希望这有帮助我刚才回答了一个类似的问题,我想我可以提供一个更简洁的解决方案:
斯威夫特2
基于“代码不同”答案的字符串扩展:
Swift 3/4/5
extension String {
func components(withLength length: Int) -> [String] {
return stride(from: 0, to: self.characters.count, by: length).map {
let start = self.index(self.startIndex, offsetBy: $0)
let end = self.index(start, offsetBy: length, limitedBy: self.endIndex) ?? self.endIndex
return self[start..<end]
}
}
}
如果要按一定长度拆分字符串,但也要考虑单词,则可以使用以下字符串扩展名:
Swift 4:
extension String {
func split(len: Int) -> [String] {
var currentIndex = 0
var array = [String]()
let length = self.characters.count
while currentIndex < length {
let startIndex = self.startIndex.advancedBy(currentIndex)
let endIndex = startIndex.advancedBy(len, limit: self.endIndex)
let substr = self.substringWithRange(Range(start: startIndex, end: endIndex))
array.append(substr)
currentIndex += len
}
return array
}
}
func splitByLength(_ length: Int, seperator: String) -> [String] {
var result = [String]()
var collectedWords = [String]()
collectedWords.reserveCapacity(length)
var count = 0
let words = self.components(separatedBy: " ")
for word in words {
count += word.count + 1 //add 1 to include space
if (count > length) {
// Reached the desired length
result.append(collectedWords.map { String($0) }.joined(separator: seperator) )
collectedWords.removeAll(keepingCapacity: true)
count = word.count
collectedWords.append(word)
} else {
collectedWords.append(word)
}
}
// Append the remainder
if !collectedWords.isEmpty {
result.append(collectedWords.map { String($0) }.joined(separator: seperator))
}
return result
}
这是对上述Matteo Piombo回答的修改
用法
Swift 5,基于@Ondrej Stocek解决方案
extension String {
func components(withMaxLength length: Int) -> [String] {
return stride(from: 0, to: self.count, by: length).map {
let start = self.index(self.startIndex, offsetBy: $0)
let end = self.index(start, offsetBy: length, limitedBy: self.endIndex) ?? self.endIndex
return String(self[start..<end])
}
}
}
扩展字符串{
func组件(带MaxLength:Int)->[字符串]{
返回步幅(从:0到:self.count,按:长度)。映射{
let start=self.index(self.startIndex,offsetBy:$0)
让end=self.index(开始,偏移:长度,限制:self.endIndex)??self.endIndex
返回字符串(self[start..My solution with a array of characters:
func split(text: String, count: Int) -> [String] {
let chars = Array(text)
return stride(from: 0, to: chars.count, by: count)
.map { chars[$0 ..< min($0 + count, chars.count)] }
.map { String($0) }
}
func拆分(文本:字符串,计数:Int)->[String]{
让chars=数组(文本)
返回步幅(从:0到:chars.count,按:count)
.map{chars[$0..
或者,对于带有子字符串的大字符串,您可以使用更优化的变体:
func split(text: String, length: Int) -> [Substring] {
return stride(from: 0, to: text.count, by: length)
.map { text[text.index(text.startIndex, offsetBy: $0)..<text.index(text.startIndex, offsetBy: min($0 + length, text.count))] }
}
func拆分(文本:字符串,长度:Int)->[子字符串]{
返回步幅(从:0到:text.count,按:长度)
.map{text[text.index(text.startIndex,offsetBy:$0)…下面是一个版本,它在以下情况下工作:
- 给定的行长度为0或更小
- 输入为空
- 一行的最后一个字不合适:该字被包装成一行
- 行的最后一个字比行长:该字被部分剪切和包装
- 一行的最后一个字比多行长:字被多次剪切和包装
扩展字符串{
函数ls_换行(最大宽度:Int)->[字符串]{
保护最大宽度>0其他{
Logger.logError(“包裹:maxWidth太小”)
返回[]
}
让addWord:(String,String)->String={(line:String,word:String)在
我是空的
单词
:“\(行)\(字)”
}
让handleWord:(([String],String),String)->([String],String)={(arg1:([String],String),word:String)在
let(acc,line):([String],String)=arg1
让lineWithWord:String=addWord(行,字)
如果lineWithWord.count maxWidth{/'word'以任何方式都不适合;笨拙地拆分。
let splitted:[String]=lineWithWord.ls_块(of:maxWidth)
let(intermediateLines,lastLine)=(splitted.ls_init,splitted.last!)
退货(acc+中间线,最后一行)
}否则{/'行'已满;以'word'开头,然后继续。
返回(acc+[行],字)
}
}
let(accLines,lastLine)=ls_words().reduce([],“”),handleWord
返回accLines+[lastLine]
}
//偷自https://stackoverflow.com/questions/32212220/how-to-split-a-string-into-substrings-of-equal-length
func ls_块(长度:Int)->[字符串]{
var startIndex=self.startIndex
变量结果=[子字符串]()
而startIndex :Array(self[0..advance()的三参数版本中可能存在已更新的问题的副本)很方便,比较。是的,我甚至没有尝试用这个索引调用任何字符串方法,我只是用任意移位推进我的变量currentIndex,并在验证这个新索引之前得到一个错误。你比较了currentIndex>endIndex
,但是currentIndex
永远不会超过endIndex
-异常是在到达之前抛出。似乎是一个有效的变体,谢谢。p.s.我会将长度更改为str.characters.count此解决方案对于Swift 2.0已经过时。当我们喜爱的表情符号出现时,使用UTF8视图可能会导致奇怪的行为。@yshilov这很有意义,我已经更新了答案。@MatteoPiombo This的回答不是“就Swift 2.0而言过时”"。事实上,它是用Xcode7和Swift2编写的。UTF8问题与Swift版本无关。@Adam我应该更详细地了解Swift 2.0。我参考了最新的Xcode 7 Beta 6。在这个Beta版中,索引方面有了重大变化。substringWithRange
不再存在。谢谢!真正的Swift解决方案,probab最好将其添加到扩展字符串中。实际上,这是最好的swift解决方案,这里有一个扩展:扩展字符串{func split(co
extension String {
func split(by length: Int) -> [String] {
var startIndex = self.startIndex
var results = [Substring]()
while startIndex < self.endIndex {
let endIndex = self.index(startIndex, offsetBy: length, limitedBy: self.endIndex) ?? self.endIndex
results.append(self[startIndex..<endIndex])
startIndex = endIndex
}
return results.map { String($0) }
}
}
extension String {
func components(withLength length: Int) -> [String] {
return stride(from: 0, to: self.characters.count, by: length).map {
let start = self.index(self.startIndex, offsetBy: $0)
let end = self.index(start, offsetBy: length, limitedBy: self.endIndex) ?? self.endIndex
return self[start..<end]
}
}
}
let str = "There are fourty-eight characters in this string"
let components = str.components(withLength: 20)
func splitByLength(_ length: Int, seperator: String) -> [String] {
var result = [String]()
var collectedWords = [String]()
collectedWords.reserveCapacity(length)
var count = 0
let words = self.components(separatedBy: " ")
for word in words {
count += word.count + 1 //add 1 to include space
if (count > length) {
// Reached the desired length
result.append(collectedWords.map { String($0) }.joined(separator: seperator) )
collectedWords.removeAll(keepingCapacity: true)
count = word.count
collectedWords.append(word)
} else {
collectedWords.append(word)
}
}
// Append the remainder
if !collectedWords.isEmpty {
result.append(collectedWords.map { String($0) }.joined(separator: seperator))
}
return result
}
let message = "Here is a string that I want to split."
let message_lines = message.splitByLength(18, separator: " ")
//output: [ "Here is a string", "that I want to", "split." ]
extension String {
func components(withMaxLength length: Int) -> [String] {
return stride(from: 0, to: self.count, by: length).map {
let start = self.index(self.startIndex, offsetBy: $0)
let end = self.index(start, offsetBy: length, limitedBy: self.endIndex) ?? self.endIndex
return String(self[start..<end])
}
}
}
func split(text: String, count: Int) -> [String] {
let chars = Array(text)
return stride(from: 0, to: chars.count, by: count)
.map { chars[$0 ..< min($0 + count, chars.count)] }
.map { String($0) }
}
func split(text: String, length: Int) -> [Substring] {
return stride(from: 0, to: text.count, by: length)
.map { text[text.index(text.startIndex, offsetBy: $0)..<text.index(text.startIndex, offsetBy: min($0 + length, text.count))] }
}
extension String {
func ls_wrap(maxWidth: Int) -> [String] {
guard maxWidth > 0 else {
Logger.logError("wrap: maxWidth too small")
return []
}
let addWord: (String, String) -> String = { (line: String, word: String) in
line.isEmpty
? word
: "\(line) \(word)"
}
let handleWord: (([String], String), String) -> ([String], String) = { (arg1: ([String], String), word: String) in
let (acc, line): ([String], String) = arg1
let lineWithWord: String = addWord(line, word)
if lineWithWord.count <= maxWidth { // 'word' fits fine; append to 'line' and continue.
return (acc, lineWithWord)
} else if word.count > maxWidth { // 'word' doesn't fit in any way; split awkwardly.
let splitted: [String] = lineWithWord.ls_chunks(of: maxWidth)
let (intermediateLines, lastLine) = (splitted.ls_init, splitted.last!)
return (acc + intermediateLines, lastLine)
} else { // 'line' is full; start with 'word' and continue.
return (acc + [line], word)
}
}
let (accLines, lastLine) = ls_words().reduce(([],""), handleWord)
return accLines + [lastLine]
}
// stolen from https://stackoverflow.com/questions/32212220/how-to-split-a-string-into-substrings-of-equal-length
func ls_chunks(of length: Int) -> [String] {
var startIndex = self.startIndex
var results = [Substring]()
while startIndex < self.endIndex {
let endIndex = self.index(startIndex, offsetBy: length, limitedBy: self.endIndex) ?? self.endIndex
results.append(self[startIndex..<endIndex])
startIndex = endIndex
}
return results.map { String($0) }
}
// could be improved to split on whiteSpace instead of only " " and "\n"
func ls_words() -> [String] {
return split(separator: " ")
.flatMap{ $0.split(separator: "\n") }
.map{ String($0) }
}
}
extension Array {
var ls_init: [Element] {
return isEmpty
? self
: Array(self[0..<count-1])
}
}