如果与字符串的长度相比,要删除/替换的字符数很小,那么您的解决方案很好,因为 while 循环中“冲突”的概率很小。您可以通过使用单个可变字符串而不是在每个步骤中分配新字符串来改进该方法:
NSString *string = @"Remove Some Characters";
int totalRemove = 5;
NSMutableString *result = [string mutableCopy];
for (int j=0; j < totalRemove; j++) {
int replaceLocation;
do {
replaceLocation = arc4random_uniform((int)[result length]);
} while ([result characterAtIndex:replaceLocation] == '_' || [result characterAtIndex:replaceLocation] == ' ');
[result replaceCharactersInRange:NSMakeRange(replaceLocation, 1) withString:@"_"];
}
如果要删除/替换的字符数与字符串的长度大致相同,那么不同的算法可能会更好。
以下代码使用C 编程语言中整数数组中的唯一随机数的思想,通过对字符串所有字符的单个循环来替换随机位置的字符。
由于您要求不替换空格字符,因此需要额外(第一次)通过。
NSString *string = @"Remove Some Characters";
int totalRemove = 5;
// First pass: Determine number of non-space characters:
__block int count = 0;
[string enumerateSubstringsInRange:NSMakeRange(0, [string length])
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
if (![substring isEqualToString:@" "]) {
count++;
}
}];
// Second pass: Replace characters at random positions:
__block int c = count; // Number of remaining non-space characters
__block int r = totalRemove; // Number of remaining characters to replace
NSMutableString *result = [string mutableCopy];
[result enumerateSubstringsInRange:NSMakeRange(0, [result length])
options:NSStringEnumerationByComposedCharacterSequences
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
if (![substring isEqualToString:@" "]) {
// Replace this character with probability r/c:
if (arc4random_uniform(c) < r) {
[result replaceCharactersInRange:substringRange withString:@"_"];
r--;
if (r == 0) *stop = YES; // Stop enumeration, nothing more to do.
}
c--;
}
}];
此解决方案的另一个优点是它可以正确处理代理项对(例如表情符号)和组合字符序列,即使它们作为两个单独的字符存储在字符串中也是如此。