【问题标题】:Comparing string arrays比较字符串数组
【发布时间】:2016-01-27 01:21:24
【问题描述】:

如果这是一个愚蠢的问题,请提前道歉。我正在开发一个简单的程序来比较两个用字符串填充的数组。一个是包含 1309 个专有名称的列表,另一个是包含 235,877 个英文单词的列表。该程序的重​​点是比较列表,并将两个列表中出现的任何单词添加到可变数组中。然后,程序将枚举可变数组并打印出两个列表上的单词。这是我的代码:

    #import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        NSString *nameString = [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames"
                                  encoding:NSUTF8StringEncoding
                                     error:NULL];
        NSString *wordString = [NSString stringWithContentsOfFile:@"/usr/share/dict/words"
                                                         encoding:NSUTF8StringEncoding
                                                            error:NULL];

        NSArray *names = [nameString componentsSeparatedByString:@"\n"];
        NSArray *words = [wordString componentsSeparatedByString:@"\n"];

        NSMutableArray *namesAndWords = [[NSMutableArray alloc]init];

        for (NSString *w in words){
            for (NSString *n in names){
                if ([[n lowercaseString] compare:w] == NSEqualToComparison){
                    [namesAndWords addObject: w];}}}

        for (NSString *item in namesAndWords){
            NSLog(@"%@", item);}


        NSLog(@"There are %lu items in the array",[namesAndWords count]);
        NSLog(@"%lu", [names count]);
        NSLog(@"%lu", [words count]);
    }
    return 0;
}

到目前为止,我已经让这个程序完全按照它应该的方式运行(显示 294 个匹配项)。我真正的问题是,当我第一次尝试比较字符串时,我是这样尝试的:

for (NSString *w in words){
            for (NSString *n in names){
                if ([n caseInsensitiveCompare:w] == NSEqualToComparison){
                    [namesAndWords addObject: w];}}}

像这样:

for (NSString *w in words){
        for (NSString *n in names){
            if ([n compare:w options:NSCaseInsensitiveSearch] == NSOrderedSame){
                [namesAndWords addObject: w];}}}

这两种方法都给了我 1602 个匹配项,并且出于某种原因将两个数组中的一些项目添加到可变数组 namesAndWords 中。因此,例如在控制台中,我会看到 Woody 和 woody 打印出来。

我尝试的另一种方法是:

    for (NSString *w in words){
        for (NSString *n in names){
            if ([n compare:w] == NSOrderedSame){
                [namesAndWords addObject: w];}}}

这样做时,它会从 names 数组中添加所有 1309 个字符串。在运行它之前,我实际上认为我不会得到任何匹配,因为我没有指定它不区分大小写。

我试图弄清楚为什么这些看起来如此相似的方法会产生不同的结果。我也在试图找出为什么if ([[n lowerCaseString] compare:w] == NSEqualToComparison) 是正确的方法。非常感谢这里的任何帮助。

【问题讨论】:

  • 不要使用NSEqualToComparison,使用NSOrderedSame。有关显示有效返回值的 compare: 方法,请参阅文档。
  • 你需要每个单词的原始大小写吗?如果您使用所有单词的小写版本创建两个 NSSet 并简单地获取两组的交集,则可以大大提高效率。
  • 是的,当找到匹配项时,我希望将 names 数组中的字符串添加到 namesAndWords 可变数组中。这样,当内容显示在控制台中时,它们就是正确的大小写。
  • 您可以使用 NSPredicate 进行更快的枚举。 HERE

标签: objective-c nsstring nsarray string-comparison


【解决方案1】:

因为下面的行检查单词只转换第一个数组的小写字符串,而不是第二个。它只获得像 m->m 这样的匹配值,包括重复项。

[[n lowercaseString] compare:w] == NSEqualToComparison

以下是我针对您的问题进行的锻炼。

NSMutableArray *actualarray1=[[NSMutableArray alloc] init];
NSMutableArray *actualarray2=[[NSMutableArray alloc] init];
actualarray1=[@[@"Apple",@"Litchi",@"Plum",@"Litchi",@"Pineapple",@"mango",@"Apple",@"berry",@"Pineapple",@"berry",@"mango",@"Apple"]mutableCopy];
actualarray2=[@[@"guava",@"Orange",@"Litchi",@"Pineapples",@"mangoes",@"Orange",@"Strawberry",@"Pineapple",@"berry",@"mango",@"Apple"]mutableCopy];
NSMutableArray *namesAndWords = [[NSMutableArray alloc]init];
for (NSString *w in actualarray1){
    for (NSString *n in actualarray2){
        if ([[n lowercaseString] compare:w] == NSEqualToComparison){
            [namesAndWords addObject: w];}}}
NSLog(@"Array without duplicates %d",(int)[namesAndWords count]);
namesAndWords=[[NSMutableArray alloc] init];
for (NSString *w in actualarray1){
    for (NSString *n in actualarray2){
        if ([n compare:w options:NSCaseInsensitiveSearch] == NSOrderedSame){
            [namesAndWords addObject: w];}}}
NSLog(@"Array with duplicates %d",(int)[namesAndWords count]);
namesAndWords=[[NSMutableArray alloc] init];
for (NSString *w in actualarray1){
    for (NSString *n in actualarray2){
        if ( [n caseInsensitiveCompare:w] == NSOrderedSame ){
            [namesAndWords addObject: w];}}}
NSLog(@"Array with duplicates %d",(int)[namesAndWords count]);

在上面的代码中,数组 1 本身和数组 2 都有重复项。请尝试一些手动迭代,这只是因为最后两次比较以一对多映射结束。在您的情况下产生重复的最后两种方法只是因为您正在使用每个循环并检查数组中的所有值。如果在比较之前删除数组中的重复项,结果会怎样?让我们看看下面的代码。

 NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:actualarray1];
        NSArray *arrayWithoutDuplicates = [orderedSet array];
        actualarray1=[arrayWithoutDuplicates mutableCopy];
        orderedSet = [NSOrderedSet orderedSetWithArray:actualarray2];
        arrayWithoutDuplicates = [orderedSet array];
        actualarray2=[arrayWithoutDuplicates mutableCopy];
        NSLog(@"%@ %@",actualarray1,actualarray2);
        namesAndWords=[[NSMutableArray alloc] init];
        for (NSString *w in actualarray1){
            for (NSString *n in actualarray2){
                if ( [n caseInsensitiveCompare:w] == NSOrderedSame ){
                    [namesAndWords addObject: w];}}}
        //Your code works like a charm!
         NSLog(@"After removing duplicates %d",(int)[namesAndWords count]);


       namesAndWords=[[NSMutableArray alloc] init];
        for (NSString *s in actualarray1){
            if([actualarray2 containsObject:s]){
                [namesAndWords addObject: s];
            }
        }
        //This is my code which eventually reduces time
         NSLog(@"Count after unique %d",(int)[namesAndWords count]);

我建议你不要使用像 [[n lowercaseString] compare:w] == NSEqualToComparison 这样的逻辑不正确的比较。因为,您只将数组中的一个对象转换为小写,并且逻辑不正确。因为,它只获取与上述代码匹配的小写数据。相反,如果您需要具有唯一值的值或在比较之前删除重复项,则可以使用 [n caseInsensitiveCompare:w] == NSOrderedSame。此外,在这种情况下不建议使用快速迭代,因为如果数组太大,性能可能会下降。

希望它能消除您的疑虑!

【讨论】:

    【解决方案2】:

    使用时:

    [[n lowercaseString] compare:w]
    

    只有当w 是小写时,你才会得到匹配。在不区分大小写的比较中,nw 的大小写都将被忽略。这将解释不同的结果。高温

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-02
      相关资源
      最近更新 更多