将文本拆分为数组,同时在Swift中保持标点符号

时间:2016-10-03 15:17:25

标签: ios arrays swift string split

我想将文本拆分成一个数组,保持标点符号与其余单词分开,所以字符串如下:

Hello, I am Albert Einstein.

应该变成这样的数组:

["Hello", ",", "I", "am", "Albert", "Einstein", "."]

我尝试使用sting.components(separatedBy: CharacterSet.init(charactersIn: " ,;;:")),但此方法会删除所有标点符号,并返回如下数组:

["Hello", "I", "am", "Albert", "Einstein"]

那么,我怎样才能得到像我的第一个例子一样的数组?

2 个答案:

答案 0 :(得分:2)

它不是很好的解决方案,但你可以尝试:

var str = "Hello, I am Albert Einstein."
var list = [String]()
var currentSubString = "";
//enumerate to get all characters including ".", ",", ";", " "
str.enumerateSubstrings(in: str.startIndex..<str.endIndex, options: String.EnumerationOptions.byComposedCharacterSequences) { (substring, substringRange, enclosingRange, value) in
    if let _subString = substring {
        if (!currentSubString.isEmpty &&
            (_subString.compare(" ") == .orderedSame
                || _subString.compare(",") == .orderedSame
                || _subString.compare(".") == .orderedSame
                || _subString.compare(";") == .orderedSame
            )
            ) {
            //create word if see any of those character and currentSubString is not empty
            list.append(currentSubString)
            currentSubString = _subString.trimmingCharacters(in: CharacterSet.whitespaces )
        } else {
            //add to current sub string if current character is not space.
            if (_subString.compare(" ") != .orderedSame) {
                currentSubString += _subString
            }
        }
    }
}


//last word
if (!currentSubString.isEmpty) {
    list.append(currentSubString)
}

在Swift3中:

var str = "Hello, I am Albert Einstein."
var list = [String]()
var currentSubString = "";
//enumerate to get all characters including ".", ",", ";", " "
str.enumerateSubstrings(in: str.startIndex..<str.endIndex, options: String.EnumerationOptions.byComposedCharacterSequences) { (substring, substringRange, enclosingRange, value) in
    if let _subString = substring {
        if (!currentSubString.isEmpty &&
            (_subString.compare(" ") == .orderedSame
                || _subString.compare(",") == .orderedSame
                || _subString.compare(".") == .orderedSame
                || _subString.compare(";") == .orderedSame
            )
            ) {
            //create word if see any of those character and currentSubString is not empty
            list.append(currentSubString)
            currentSubString = _subString.trimmingCharacters(in: CharacterSet.whitespaces )
        } else {
            //add to current sub string if current character is not space.
            if (_subString.compare(" ") != .orderedSame) {
                currentSubString += _subString
            }
        }
    }
} 


//last word
if (!currentSubString.isEmpty) {
    list.append(currentSubString)
}

这个想法是循环所有角色并同时创建单词。单词是一组不是,.;的连续字符。因此,在创建循环中的单词期间,如果我们看到其中一个字符,则我们完成当前单词,并且构造中的当前单词不为空。 要根据您的输入细分步骤:

  1. 获取H(不是空格或其他终端字符) - &GT; currentSubString =&#34; H&#34;
  2. 获取e(不是空格或其他终端字符) - &GT; currentSubString =&#34;他&#34;
  3. 获取l(不是空格或其他终端字符) - &GT; currentSubString =&#34; Hel&#34;
  4. 获取l(不是空格或其他终端字符) - &GT; currentSubString =&#34;地狱&#34;
  5. 获取o(不是空格或其他终端字符) - &GT; currentSubString =&#34;你好&#34;
  6. 获取.(是终端字符)
    • - &GT;因为currentSubString不为空,添加到list并重新构造下一个单词,然后list = [&#34; Hello&#34;]
    • - &GT; currentSubString =&#34;。&#34; (我使用修剪的原因只是为了删除如果我得到这个角色。但对于其他终端角色,我们必须保留下一个字。
  7. 获取(是空格字符)
    • - &GT;因为currentSubString不为空,添加到list并重新开始构建 - &gt; list = [&#34; Hello&#34;,&#34;。&#34;]
    • - &GT; currentSubString =&#34;&#34; (修剪)。 ......等等。

答案 1 :(得分:0)

从我的评论中解释......将regular expressions想象成一种很好地在字符串中找到模式的方法。在您的情况下,模式是单词(字母组),其中包含其他可能的符号(标点符号)。

在我的评论中加入正则表达式(我已在此处进行了扩展),例如:([,\.\:\"])*([A-Za-z0-9\']*)([,\.\:\"])*

在那里,我们有3 groups。第一个搜索任何符号(例如前导引号)。第二个是搜索字母,数字和撇号(因为人们喜欢连接单词,比如&#34;我&#39; m&#34;)。第三组搜索任何尾随标点符号。

编辑注意:上面的组用括号(和)表示,而[和]括号表示搜索的可接受字符。因此,例如,[A-Z]表示来自A-Z的所有大写字母都是可接受的。 [A-Za-z]可让您同时获得上下两个,而[A-Za-z0-9]包含0-9中的所有字母和数字。当然,有写这篇的速记版本,但是你将会发现这些版本。

所以现在我们有办法将所有单词和标点符号分开,现在你需要实际使用它,按照以下方式做一些事情:

func find(value: NSString) throws -> [NSString] {
    let regex = try NSRegularExpression(pattern: "([,\\.\\:\\\"])*([A-Za-z0-9\\']*)([,\\.\\:\\\"])*") // Notice you have to escape the values in code
    let results = regex.matches(in: value, range: NSRange(location: 0, length: nsString.length))
    return results.map({ value.substring(with: $0.range) }).filter({ $0 != nil })
}

这应该为您提供给方法提供的String值中的每个非零组。

当然,最后一种过滤方法可能没有必要,但我对Swift处理正则表达式的方式还不够熟悉。

但这绝对应该指向正确的方向......

干杯〜