我正在尝试编写一个搜索 NSString 的方法,确定字符串中的单个单词是否超过 6 个字符,然后用其他单词替换该单词(像“hello”这样的任意词)。
我从一个很长的段落开始,最后需要一个 NSString 对象,其格式和间距不受查找和替换的影响。
我正在尝试编写一个搜索 NSString 的方法,确定字符串中的单个单词是否超过 6 个字符,然后用其他单词替换该单词(像“hello”这样的任意词)。
我从一个很长的段落开始,最后需要一个 NSString 对象,其格式和间距不受查找和替换的影响。
使用简单的解决方案有几个微妙的问题componentsSeparatedByString:
:
假设“-”的替换词是一个字符串,如...
“基本上,”DHC 总结道,
“bokanovskification 包括一系列发展停滞。”</p>
...会导致...
– DHC – – 一系列 – 的 –</p>
...而正确的输出是:
“-”,DHC-,
“--一系列-的-。”</p>
幸运的是,Cocoa 中有一个更好但更简单的解决方案:-[NSString enumerateSubstringsInRange:options:usingBlock:]
options
它提供了对参数定义的子字符串的快速迭代。一种可能性是NSStringEnumerationByWords
枚举实际上是真实单词的所有子字符串(在当前语言环境中)。它甚至可以检测不使用分隔符(空格)分隔单词的语言中的单个单词,例如日语。
这是一个适用于行话文件(1.6 MB,237,239 字)的简单演示项目。它比较了三种不同的解决方案:
它的核心是替换循环:
NSMutableString *result = [NSMutableString stringWithCapacity:[originalString length]];
__block NSUInteger location = 0;
[originalString enumerateSubstringsInRange:(NSRange){0, [originalString length]}
options:NSStringEnumerationByWords | NSStringEnumerationLocalized | NSStringEnumerationSubstringNotRequired
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
if (substringRange.length > maxChar) {
NSString *charactersBetweenLongWords = [originalString substringWithRange:(NSRange){ location, substringRange.location - location }];
[result appendString:charactersBetweenLongWords];
[result appendString:replaceWord];
location = substringRange.location + substringRange.length;
}
}];
[result appendString:[originalString substringFromIndex:location]];
正如Monolo所指出的,建议的代码使用NSString
's 长度来确定单词的字符数。至少可以说,这是一个值得怀疑的方法。实际上,字符串length
指定了用于对字符串进行编码的代码片段的数量,该值通常与人类假设的字符数不同。
由于术语“字符”在各种上下文中具有不同的含义,并且 OP 没有指定使用哪种字符数,我只是将代码保持原样。如果您想要不同的计数,请参阅讨论该主题的文档:
正如您从答案中看到的那样,有几种方法可以完成您所追求的目标,但我个人更喜欢使用NSString
该类的stringByReplacingOccurrencesOfString:withString:options:range:
方法,该方法正是为了用另一个字符串替换子字符串。
在您的情况下,我们需要使用NSRegularExpressionSearch
允许识别具有 7 个或更多字母(即,如您所说的超过 6 个字母)的单词的选项。
如果您使用\w
*字符表达式,您将自动获得 Unicode 支持,因此它适用于 Apple(实际上是 ICU)支持的多种语言。
它是这样的:
NSString *stringWithLongWords = @"There are some words of extended length in this text. One of them is Escher's. They will be identified with a regular expression and changed for some arbitrary word.";
NSString *overSixCharsPattern = @"(?w)\\b[\\w]{7,}\\b";
NSString *replacementString = @"hello";
NSString *result = [stringWithLongWords stringByReplacingOccurrencesOfString: overSixCharsPattern
withString: replacementString
options: NSRegularExpressionSearch
range: NSMakeRange(0, stringWithLongWords.length)];
这些\b
表达式表示一个单词边界,它确保整个单词被匹配和替换。w
修饰符\b
使用更自然的单词边界定义。具体来说,它处理字符串“Escher's”,@NikolaiRuhe 提到的示例。文档在这里,这里有边界检测的具体讨论。
另请注意,文字NSString
(即,您直接在 Objective-C 源文件中键入的文字)需要在源代码中使用两个反斜杠才能在生成的字符串中生成一个。
NSString 文档中有更多信息
*技术上\w
匹配单词字符,其中还包括正则表达式使用的定义中的数字。