【问题标题】:iPhone sdk: how to delete duplicates in the NSArrayiPhone sdk:如何删除 NSArray 中的重复项
【发布时间】:2011-03-12 07:32:16
【问题描述】:

嗨,我的 NSArray 包含这样的重复项(我必须删除重复项)

标题:父亲节

标题:父亲节

标题:父亲节

标题:选举日

标题:选举日

标题:选举日

标题:复活节

标题:复活节

标题:地球日

标题:地球日

标题:地球日

标题:五月五日节

标题:五月五日节

标题:五月五日节

标题:平安夜

标题:平安夜

标题:平安夜

标题:圣诞节 标题:圣诞节 标题:圣诞节

我只保留一个名字,不需要其他重复的名字。 我是怎么做到的,请用清晰的解释指导我,以解决这个问题。 谢谢你。

【问题讨论】:

    标签: iphone objective-c nsarray


    【解决方案1】:

    如果你关心排序,你可以创建一个新的可变数组,循环遍历旧数组中的每个对象,并且只在它不存在时添加它:

    NSMutableArray *uniqueItems = [NSMutableArray array];
    for (id item in allItems)
        if (![uniqueItems containsObject:item])
            [uniqueItems addObject:item];
    

    如果没有,那么只使用一个集合会简单得多:

    NSSet *uniqueItems = [NSSet setWithArray:allItems];
    

    【讨论】:

    • 我建议首先使用NSSet
    • “关心排序”解决方案的运行时复杂性不是很好。 NSArray 的 containsObject 具有线性运行时复杂性,即它可能必须与数组中的每个项目进行比较。涉及存储桶的解决方案(例如 NSSet)可为您提供更好的性能。
    • 另外,他的输入数组似乎已排序(尽管 OP 没有明确指定这一点)——所以在这种情况下你的解决方案也有点复杂。
    • 还有NSOrderedSet,自iOS 5/OS X 10.7起可用
    【解决方案2】:

    您希望删除重复数据的 NSArray 是否已经排序?从你的问题看来是这样。在这种情况下,下面的代码就可以了:

    NSMutableArray *uniqueItems = [NSMutableArray array];
    
    id lastSeenUniqueObject = nil;
    
    for (NSObject *item in allItems) {
        if (![item isEqual:lastSeenUniqueObject]) {
            [uniqueItems addObject:item];
            lastSeenUniqueObject = item;
        }
    }
    

    与 rpetrich 答案的(大约)N^2 复杂度相比,这具有 N 的运行时复杂度(即快速)。

    如果您知道 Array 的内容已排序,您有两种选择:

    A) 只需对其进行排序,然后应用上述算法,这将提供 n log n 运行时复杂度(仍然比 N^2 好得多),

    B) 使用NSMutableSet 来跟踪已经看到的对象(或任何其他使用桶和散列的数据结构)。代码是这样的:

    NSMutableArray *uniqueItems = [NSMutableArray array];
    
    NSMutableSet *seenItems = [NSMutableSet set];
    
    for (NSObject *item in allItems) {
        if (![seenItems containsObject:item]) {
            [uniqueItems addObject:item];
            [seenItems addOBject:item];
        }
    }
    

    这也提供了比 N^2 更好的运行时间。

    【讨论】:

      【解决方案3】:

      看这个简单..

      NSMutableArray *dateArray = [[NSMutableArray alloc]initWithObjects:@"December 29,2010", 
                                   @"December 28,2010",
                                   @"December 22,2010",
                                   @"December 22,2010",
                                   @"December 22,2010",@"December 21,2010",@"December 28,2010",nil];
      

      为了避免重复使用这个...

      NSSet *cleanedArray = [NSSet setWithArray:dateArray];
      NSArray *array = [[NSArray alloc]initWithArray:[cleanedArray allObjects]];
      
      for (int i=0; i<[array count]; i++) {
          NSLog(@"The Given Array is %@",[array objectAtIndex:i]);
      }
      

      【讨论】:

      • 当你分配一个 NSSet 时,它不会神奇地变成一个 NSArray。它仍然是一个 NSSet,你在它上面使用的所有 NSArray 方法都会导致崩溃。
      • 你试过了吗?将NSLog(@"First Object: %@", [cleanedArray objectAtIndex:0]); 添加到您的代码中。
      • 我同意你的观点....这是简单的方法。但在询问之前他应该指定 tat 不应该使用 NSSET.......
      • 这与他的问题或NSSet无关。当你写NSArray *foo = [NSSet ...时这是错误的
      • 现在这是正确的.. 它仍然是 NSArray 而不是 nsset... Fluch 先生
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-10
      • 1970-01-01
      • 2012-08-10
      相关资源
      最近更新 更多