I have a problem where I need to invert two characters within a string. For example, if my string is "a*b/c" and I want to replace occurrences of * with / and / with *. I want the resulting string to be "a/b*c".
我有一个问题需要在一个字符串中反转两个字符。例如,如果我的字符串是“a*b/c”,我想用/和/用*替换出现的*。我希望得到的字符串是“a/b*c”。
Using the method stringByReplacingOccurrenceOfString:
doesn't work because I don't want the first round of replacements to affect the second:
使用方法stringByReplacingOccurrenceOfString:不工作,因为我不想第一轮的替换影响第二个:
string = @"a*b/c";
[string stringByReplacingOccurrencesOfString:@"*" withString:@"/"];
[string stringByReplacingOccurrencesOfString:@"/" withString:@"*"];
This results in "a*b*c", which is not what I want. Does anybody know an efficient way of accomplishing this?
这导致了“a*b*c”,这不是我想要的。有人知道有效的方法吗?
4 个解决方案
#1
4
string = @"a*b/c";
[string stringByReplacingOccurrencesOfString:@"*" withString:@"&"];
[string stringByReplacingOccurrencesOfString:@"/" withString:@"*"];
[string stringByReplacingOccurrencesOfString:@"&" withString:@"/"];
#2
2
Use an NSScanner
to move through the string and substitute each character as it is found. This way, all substitutions are done in one pass and you're never looking at a position twice.
使用NSScanner遍历字符串,并按找到的字符替换每个字符。这样,所有的替换都是一次完成的,你永远不会看到一个位置两次。
NSMutableString * fixedUpString = [NSMutableString string];
NSScanner * scanner = [NSScanner scannerWithString:origString];
NSCharacterSet * subCharacters = [NSCharacterSet characterSetWithCharactersInString:@"*/"];
while( ![scanner isAtEnd] ){
// Pick up other characters.
NSString * collector;
if( [scanner scanUpToCharactersInSet:subCharacters intoString:&collector] ){
[fixedUpString appendString:collector];
}
// This can easily be generalized with a loop over a mapping from
// found characters to substitutions
// Check which one we found
if( [scanner scanString:@"*" intoString:nil] ){
// Append the appropriate substitution.
[fixedUpString appendString:@"/"];
}
else /* if( [scanner scanString:@"/" intoString:nil] ) */ {
[fixedUpString appendString:@"*"];
}
}
fixedUpString
now contains the substituted content.
fixedUpString现在包含替换的内容。
As I noted in the comment, this can be generalized very easily to any number of substitutions:
正如我在评论中提到的,这可以很容易地推广到任何数量的替换:
NSDictionary * substitutions = @{ @"a" : @"z", @"b" : @"y", ... };
NSCharacterSet * keyChars = [NSCharacterSet characterSetWithCharactersInString:[[substitutions allKeys] componentsJoinedByString:@""]];
...
// Check which one we found
for( NSString * keyChar in [substitutions allKeys] ){
if( [scanner scanString:keyChar intoString:nil ){
[fixedUpString appendString:substitutions[keyChar]];
break;
}
}
#3
1
I had to have a go at this without using the intermediary &
character, and though this is certainly more convoluted, this also appears to work:
我必须在不使用中介和字符的情况下进行这一操作,尽管这肯定更复杂,但这似乎也适用:
int main(int argc, char *argv[])
{
NSString *s = @"1*2/3*4*5*6*7*8/2";
NSArray *stars = [s componentsSeparatedByString:@"*"];
NSMutableArray *slashes = [NSMutableArray array];
for (NSString *star in stars)
{
[slashes addObject:[star componentsSeparatedByString:@"/"]];
}
NSMutableArray *newStars = [NSMutableArray array];
for (NSArray *slash in slashes)
{
[newStars addObject:[slash componentsJoinedByString:@"*"]];
}
NSString *newString = [newStars componentsJoinedByString:@"/"];
NSLog(@"%@", newString);
return 0;
}
Output:
输出:
1/2*3/4/5/6/7/8*2
1/2 * 3/4/5/6/7/8 * 2
#4
0
Here's my take on a solution, since I could not find a builtin method that would do what you are looking for.
这是我的一个解决方案,因为我找不到一个可以做你想做的事情的内置方法。
NSString *string = @"a*b/c";
NSDictionary *swapings = @{@"*" : @"/", @"/" : @"*"};
NSString *newString = [self swap:swapings inString:string];
NSLog(@"'%@' became '%@'", string, newString);
# ... somewhere in self :
-(NSString *)swap:(NSDictionary *)swapings inString:(NSString *)string {
NSMutableArray *letters = [NSMutableArray array];
for (int i = 0; i < [string length]; i++) {
NSString *letter = [string substringWithRange:NSMakeRange(i, 1)];
[letters addObject:letter];
}
for (int i=0; i<letters.count; i++) {
NSString *letter = [letters objectAtIndex:i];
for(NSString *token in [swapings allKeys]) {
if ([letter isEqualToString:token]) {
letter = [swapings valueForKey:token];
break;
}
}
[letters replaceObjectAtIndex:i withObject:letter];
}
return [letters componentsJoinedByString:@""];
}
#1
4
string = @"a*b/c";
[string stringByReplacingOccurrencesOfString:@"*" withString:@"&"];
[string stringByReplacingOccurrencesOfString:@"/" withString:@"*"];
[string stringByReplacingOccurrencesOfString:@"&" withString:@"/"];
#2
2
Use an NSScanner
to move through the string and substitute each character as it is found. This way, all substitutions are done in one pass and you're never looking at a position twice.
使用NSScanner遍历字符串,并按找到的字符替换每个字符。这样,所有的替换都是一次完成的,你永远不会看到一个位置两次。
NSMutableString * fixedUpString = [NSMutableString string];
NSScanner * scanner = [NSScanner scannerWithString:origString];
NSCharacterSet * subCharacters = [NSCharacterSet characterSetWithCharactersInString:@"*/"];
while( ![scanner isAtEnd] ){
// Pick up other characters.
NSString * collector;
if( [scanner scanUpToCharactersInSet:subCharacters intoString:&collector] ){
[fixedUpString appendString:collector];
}
// This can easily be generalized with a loop over a mapping from
// found characters to substitutions
// Check which one we found
if( [scanner scanString:@"*" intoString:nil] ){
// Append the appropriate substitution.
[fixedUpString appendString:@"/"];
}
else /* if( [scanner scanString:@"/" intoString:nil] ) */ {
[fixedUpString appendString:@"*"];
}
}
fixedUpString
now contains the substituted content.
fixedUpString现在包含替换的内容。
As I noted in the comment, this can be generalized very easily to any number of substitutions:
正如我在评论中提到的,这可以很容易地推广到任何数量的替换:
NSDictionary * substitutions = @{ @"a" : @"z", @"b" : @"y", ... };
NSCharacterSet * keyChars = [NSCharacterSet characterSetWithCharactersInString:[[substitutions allKeys] componentsJoinedByString:@""]];
...
// Check which one we found
for( NSString * keyChar in [substitutions allKeys] ){
if( [scanner scanString:keyChar intoString:nil ){
[fixedUpString appendString:substitutions[keyChar]];
break;
}
}
#3
1
I had to have a go at this without using the intermediary &
character, and though this is certainly more convoluted, this also appears to work:
我必须在不使用中介和字符的情况下进行这一操作,尽管这肯定更复杂,但这似乎也适用:
int main(int argc, char *argv[])
{
NSString *s = @"1*2/3*4*5*6*7*8/2";
NSArray *stars = [s componentsSeparatedByString:@"*"];
NSMutableArray *slashes = [NSMutableArray array];
for (NSString *star in stars)
{
[slashes addObject:[star componentsSeparatedByString:@"/"]];
}
NSMutableArray *newStars = [NSMutableArray array];
for (NSArray *slash in slashes)
{
[newStars addObject:[slash componentsJoinedByString:@"*"]];
}
NSString *newString = [newStars componentsJoinedByString:@"/"];
NSLog(@"%@", newString);
return 0;
}
Output:
输出:
1/2*3/4/5/6/7/8*2
1/2 * 3/4/5/6/7/8 * 2
#4
0
Here's my take on a solution, since I could not find a builtin method that would do what you are looking for.
这是我的一个解决方案,因为我找不到一个可以做你想做的事情的内置方法。
NSString *string = @"a*b/c";
NSDictionary *swapings = @{@"*" : @"/", @"/" : @"*"};
NSString *newString = [self swap:swapings inString:string];
NSLog(@"'%@' became '%@'", string, newString);
# ... somewhere in self :
-(NSString *)swap:(NSDictionary *)swapings inString:(NSString *)string {
NSMutableArray *letters = [NSMutableArray array];
for (int i = 0; i < [string length]; i++) {
NSString *letter = [string substringWithRange:NSMakeRange(i, 1)];
[letters addObject:letter];
}
for (int i=0; i<letters.count; i++) {
NSString *letter = [letters objectAtIndex:i];
for(NSString *token in [swapings allKeys]) {
if ([letter isEqualToString:token]) {
letter = [swapings valueForKey:token];
break;
}
}
[letters replaceObjectAtIndex:i withObject:letter];
}
return [letters componentsJoinedByString:@""];
}