用大写字母拆分Swift中的字符串

时间:2016-09-20 11:11:28

标签: arrays swift string split

我想用大写字母将一个简单的String拆分成一个数组。看起来应该是这样的:

let teststring = "NaCuHHe"

,结果应为:

["Na", "Cu", "H", "He"]

我尝试了以下内容:

func capitalLetters(s: String) -> [Character] {
    return s.characters.filter { ("A"..."Z").contains($0) }
}

我搜索了文档和其他网站,但我没有找到任何有用的东西。我在最后。我不知道该怎么做更多因此我真的很新。它仍然只给我资本,我不知道如何改变它给了我第一资本背后的东西。

8 个答案:

答案 0 :(得分:7)

(Swift 3)

我们可以让自己受到split function in Sequence的实现的启发,并实现我们自己的splitBefore方法(在分隔符之前拆分,省略空子序列),使分隔符保持在拆分序列中。 / p>

extension Sequence {
    func splitBefore(
        separator isSeparator: (Iterator.Element) throws -> Bool
    ) rethrows -> [AnySequence<Iterator.Element>] {
        var result: [AnySequence<Iterator.Element>] = []
        var subSequence: [Iterator.Element] = []

        var iterator = self.makeIterator()
        while let element = iterator.next() {
            if try isSeparator(element) {
                if !subSequence.isEmpty {
                    result.append(AnySequence(subSequence))
                }
                subSequence = [element]
            }
            else {
                subSequence.append(element)
            }
        }
        result.append(AnySequence(subSequence))
        return result
    }
}

使用如下

/* help property */
extension Character {
    var isUpperCase: Bool { return String(self) == String(self).uppercased() }
}

/* example usage */  
let teststring = "NaCuHHe"
let splitted = teststring
    .characters
    .splitBefore(separator: { $0.isUpperCase })
    .map{String($0)}
print(splitted) // ["Na", "Cu", "H", "He"]

答案 1 :(得分:6)

功能编程风格的另一种解决方案

isUppercase

首先让我们定义一个简单的方法来检查一个Character是否为大写

extension Character {
    var isUppercase: Bool { return String(self).uppercased() == String(self) }
}

索引

接下来我们需要大写字符的索引

let indexes = Set(text
    .characters
    .enumerated()
    .filter { $0.element.isUppercase }
    .map { $0.offset })

构建结果

现在我们可以构建结果

let chunks = text
    .characters
    .map { String($0) }
    .enumerated()
    .reduce([String]()) { chunks, elm -> [String] in
        guard !chunks.isEmpty else { return [elm.element] }
        guard !indexes.contains(elm.offset) else { return chunks + [String(elm.element)] }

        var chunks = chunks
        chunks[chunks.count-1] += String(elm.element)
        return chunks
    }

输出

["Na", "Cu", "H", "He"]

答案 2 :(得分:3)

另一种方式是:

let input = "NaCuHHe"

var result = [String]()
var lastIndex = 0
for (index, letter) in input.characters.enumerate() where String(letter) != String(letter).lowercaseString {
    guard index != lastIndex else { continue }
    result += [input.substringWithRange(input.startIndex.advancedBy(lastIndex) ..< input.startIndex.advancedBy(index))]
    lastIndex = index
}
result += [input.substringWithRange(input.startIndex.advancedBy(lastIndex) ..< input.endIndex)]

结果为["Na", "Cu", "H", "He"]

答案 3 :(得分:2)

派对有点晚了,但是这里使用空格分隔是一种简单的Swift 3方法。可能不像函数或迭代器方法那样优雅,但它不涉及在现有类上进行任何自定义扩展。

    let originalString = "NaCuHHe"
    var newStringArray: [String] = []
    for character in originalString.characters {
        if String(character) == String(character).uppercased() {
            newStringArray.append(" ")
        }
        newStringArray.append(String(character))
    }

    let newString = newStringArray.joined().trimmingCharacters(in: .whitespacesAndNewlines).components(separatedBy: " ")
    print(newString) // Returns ["Na", "Cu", "H", "He"]

答案 4 :(得分:0)

dfri的答案,对Swift 4进行了很大的修改

他的序列扩展名相同,但所用的扩展名不同:

    extension Sequence {
    func splitBefore(
        separator isSeparator: (Iterator.Element) throws -> Bool
    ) rethrows -> [AnySequence<Iterator.Element>] {
        var result: [AnySequence<Iterator.Element>] = []
        var subSequence: [Iterator.Element] = []

        var iterator = self.makeIterator()
        while let element = iterator.next() {
            if try isSeparator(element) {
                if !subSequence.isEmpty {
                    result.append(AnySequence(subSequence))
                }
                subSequence = [element]
            }
            else {
                subSequence.append(element)
            }
        }
        result.append(AnySequence(subSequence))
        return result
    }
}

使用的字符串扩展名:

extension String {

var isLowercase: Bool {
    return self == self.lowercased()
}

var isUppercase: Bool {
    return self == self.uppercased()
}

,然后由于Swift 4不推荐使用字符,因此将其用作如下

    let teststring = "NaCuHHe"
    let splitted = teststring
    .splitBefore(separator: { $0.isUppercase })
    .map{String($0)}
    print(splitted) // ["Na", "Cu", "H", "He"]

答案 5 :(得分:0)

Swift 4中的答案

另一种方法是将最后一个单词(以大写字母开头)弹出到结果列表中,直到在给定的字符串中找不到更多的大写字母为止。

extension String {
    func splitWord() -> [String] {
        var result = [String]()
        var temp = self
        var done = false
        while !done {
            if let index = temp.lastIndex(where: { $0.isUppercase }) {
                result.insert(String(temp[index...]), at: 0)
                temp = String(temp[..<index])
                done = temp.distance(from: temp.startIndex, to: index) == 0
            }
            else {
                result.insert(temp, at: 0)
                done = true
            }
        }
        return result
    }
}

答案 6 :(得分:0)

使用正则表达式-

func splitYourString(_ s: String) ->[String] {
let regex = try! NSRegularExpression(pattern: "([a-z]*)([A-Z])") //<-Use capturing, `([a-z]*)`->$1, `([A-Z])`->$2
return regex.stringByReplacingMatches(in: s, range: NSRange(0..<s.utf16.count),
                                      withTemplate: "$1 $2").trimmingCharacters(in: .whitespacesAndNewlines) .components(separatedBy: " ")
}
print(splitYourString("NaCuHHe"))     //["Na", "Cu", "H", "He"]

答案 7 :(得分:0)

Swift 5中的答案。

从Apple实施split function in Collection中拆分得到启发。

我所做的是改变子序列索引的创建方式。

在原始实现中,当您按下分隔符时:

  1. 向子序列数组添加新的子序列
  2. 在分隔符之后形成新索引
  3. 将该索引归因于下一个子序列开始

在我的实现中:

  1. 向子序列数组添加新的子序列
  2. 将当前索引归因于下一个子序列开始
  3. 在分隔符后形成新索引

    extension Collection {
    @inlinable
    public __consuming func split(
        maxSplits: Int = Int.max,
        omittingEmptySubsequences: Bool = true,
        includeSeparator: Bool = false,
        whereSeparator isSeparator: (Element) throws -> Bool
    ) rethrows -> [SubSequence] {
        var result: [SubSequence] = []
        var subSequenceStart: Index = startIndex
    
        func appendSubsequence(end: Index) -> Bool {
            if subSequenceStart == end && omittingEmptySubsequences {
                return false
            }
            result.append(self[subSequenceStart..<end])
            return true
        }
    
        if maxSplits == 0 || isEmpty {
            _ = appendSubsequence(end: endIndex)
            return result
        }
    
        var subSequenceEnd = subSequenceStart
        let cachedEndIndex = endIndex
        while subSequenceEnd != cachedEndIndex {
            if try isSeparator(self[subSequenceEnd]) {
                let didAppend = appendSubsequence(end: subSequenceEnd)
                if includeSeparator {
                    subSequenceStart = subSequenceEnd
                    formIndex(after: &subSequenceEnd)
                } else {
                    formIndex(after: &subSequenceEnd)
                    subSequenceStart = subSequenceEnd
                }
    
                if didAppend && result.count == maxSplits {
                    break
                }
                continue
            }
            formIndex(after: &subSequenceEnd)
        }
    
        if subSequenceStart != cachedEndIndex || !omittingEmptySubsequences {
            result.append(self[subSequenceStart..<cachedEndIndex])
        }
    
        return result
    }
    

    测试结果为:

       let splitedString = "NaCuHHe".split(includeSeparator: true, whereSeparator: { $0.isUppercase })
       print(splitedString) // ["Na", "Cu", "H", "He"]