【问题标题】:Remove only first instance of a character from a list of characters从字符列表中仅删除字符的第一个实例
【发布时间】:2010-05-29 07:29:04
【问题描述】:

这就是我想要做的。我有 2 个字符串,我想确定一个字符串是否是另一个字符串的排列。我想简单地从字符串 B 中删除字符串 A 中的字符,以确定是否还剩下任何字符。如果否,则通过。

但是,除非单词中有多个字母,否则我需要确保仅删除每个字母的 1 个实例(并非所有出现)。

一个例子:

字符串 A:不能

字符串 B:连接

结果:-o-nec-

到目前为止,用 NSString 和 NSScanner 进行实验没有产生任何结果。

【问题讨论】:

    标签: objective-c cocoa macos


    【解决方案1】:

    嗯,我们走吧:

    NSString *stringA = @"cant";
    NSString *stringB = @"connect";
    
    NSUInteger length = [stringB length];
    NSMutableCharacterSet *charsToRemove = [NSMutableCharacterSet characterSetWithCharactersInString:stringA];
    
    unichar *buffer = calloc(length, sizeof(unichar));
    [stringB getCharacters:buffer range:NSMakeRange(0, length)];
    
    for (NSUInteger i = 0; i < length; i++)
    {
        if ([charsToRemove characterIsMember:buffer[i]])
        {
            [charsToRemove removeCharactersInRange:NSMakeRange(buffer[i], 1)];
            buffer[i] = '-';
        }
    }
    
    NSString *result = [NSString stringWithCharacters:buffer length:length];
    
    free (buffer);
    

    【讨论】:

    • 对不起,刚刚看到 stringA 和 stringB 和结果,没有完全阅读问题;)
    【解决方案2】:

    一种低效但简单的方法可能是这样的(这是作为 NSString 上的一个类别实现的,但它也可以很容易地成为一个采用两个字符串的方法或函数):

    @implementation NSString(permutation)
    - (BOOL)isPermutation:(NSString*)other
    {
        if( [self length] != [other length] ) return NO;
        if( [self isEqualToString:other] )    return YES;
        NSUInteger length = [self length];
        NSCountedSet* set1 = [[[NSCountedSet alloc] initWithCapacity:length] autorelease];
        NSCountedSet* set2 = [[[NSCountedSet alloc] initWithCapacity:length] autorelease];
        for( int i = 0; i < length; i++ ) {
            NSRange range = NSMakeRange(i, 1);
            [set1 addObject:[self substringWithRange:range]];
            [set2 addObject:[self substringWithRange:range]];
        }
        return [set1 isEqualTo:set2];
    }
    @end
    

    【讨论】:

    • 此解决方案假定两个单词的长度相同,在这种情况下不起作用。我还需要能够检查更大单词的子集。对不起,如果我不清楚:(
    • @Luke:您可以轻松地删除长度位并使用两个字符串中较大的一个作为长度。根据您的问题,我认为您想检查一个字符串是否是另一个字符串的排列,如果字符串的长度不同,这将是错误的。
    • 是的。那是我的错。很抱歉混淆了。我的意思是这个词不是这个词的子集或排列,意思是给定词 B 中的字母,我可以不重复就做 A。下次会尝试更清楚。不过感谢您的帮助!
    【解决方案3】:

    这将返回您的示例要求的内容...

    NSString* a = @"cant";
        NSString* b = @"connect";
    
        NSMutableString* mb = [NSMutableString stringWithString:b];
        NSUInteger i;
        for (i=0; i<[a length]; i++) {
            NSString* theLetter = [a substringWithRange:NSMakeRange(i, 1)];
            NSRange r = [mb rangeOfString:theLetter];
            if (r.location != NSNotFound) {
                [mb replaceCharactersInRange:r withString:@"-"];
            }
        }
        NSLog(@"mb: %@", mb);
    

    但是,我不会将其称为排列。对我来说,只有当字符串“a”中的所有字符都包含在字符串“b”中时,排列才会成立。在您的示例中,由于 cant 中的字母 a 不在字符串 b 中,所以我会说 cant 不是连接的排列。有了这个定义,我会使用这个:

    -(BOOL)isString:(NSString*)firstString aPermutationOfString:(NSString*)secondString {
        BOOL isPermutation = YES;
        NSMutableString* mb = [NSMutableString stringWithString:secondString];
        NSUInteger i;
        for (i=0; i<[firstString length]; i++) {
            NSString* theLetter = [firstString substringWithRange:NSMakeRange(i, 1)];
            NSRange r = [mb rangeOfString:theLetter];
            if (r.location != NSNotFound) {
                [mb deleteCharactersInRange:r];
            } else {
                return NO;
            }
    
        }
        return isPermutation;
    }
    

    【讨论】:

    • 是的。我想我正在寻找的是更大字符集的派生或子集。话虽如此,我将此答案标记为正确,因为它提供了这两种功能。我还测试了提供的所有代码示例,它们工作正常。作为旁注,我有工作代码检查 char 值并移动内存块,但一直发现我的内存不足,即使它似乎没有泄漏。解决方案或问题是我如何设置 NSAutoreleasePool。因此,如果有人在批处理操作中使用此代码,请检查一下:)谢谢大家!
    猜你喜欢
    • 1970-01-01
    • 2018-09-23
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    • 2012-09-23
    • 1970-01-01
    • 2018-12-03
    相关资源
    最近更新 更多