Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 如何将字符串拆分为等长的子字符串_String_Swift_Swift2 - Fatal编程技术网

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