目标C中从NSMutableArray中删除重复值的最佳方法-C?

目标C中从NSMutableArray中删除重复值的最佳方法-C?

删除重复值的最佳方法(NSString)来自NSMutableArray目标-C?

这是最简单和正确的方法吗?

uniquearray = [[NSSet setWithArray:yourarray] allObjects];


暮色呼如
浏览 397回答 3
3回答

达令说

我知道这是一个老问题,但是在NSArray 如果你不关心命令.如果我们用来自键值编码的对象运算符我们可以这样做:uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];如安托巴还注意到,可以根据属性删除重复项。例如:@distinctUnionOfObjects.name

狐的传说

是的,使用NSSet是一种明智的方法。为了补充Jim Puls的回答,这里有一种在保留订单的同时剥离副本的替代方法://&nbsp;Initialise&nbsp;a&nbsp;new,&nbsp;empty&nbsp;mutable&nbsp;array&nbsp;NSMutableArray&nbsp;*unique&nbsp;=&nbsp;[NSMutableArray&nbsp;array];for&nbsp;(id&nbsp;obj&nbsp;in&nbsp;originalArray)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(![unique&nbsp;containsObject:obj])&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[unique&nbsp;addObject:obj]; &nbsp;&nbsp;&nbsp;&nbsp;}}它基本上与Jim的方法相同,但将唯一项复制到一个新的可变数组中,而不是从原始数组中删除重复项。这使得在具有大量重复(不需要复制整个数组的副本)的大型数组的情况下,它的内存效率略高一些,而且在我看来,它的可读性更高一些。请注意,在任何一种情况下,都要检查目标数组中是否已经包含了项(使用containsObject:在我的例子中,或者indexOfObject:inRange:(在Jim‘s中)不能很好地扩展到大型数组。这些检查在O(N)时间内运行,这意味着如果将原始数组的大小增加一倍,那么每张支票要跑两倍的时间。由于您正在对数组中的每个对象进行检查,您还将运行更多的这些更昂贵的检查。整个算法(我的和Jim的)运行在O(N)中2)时间,随着原始数组的增长,时间很快就会变得昂贵。要将其降到O(N)时间,您可以使用NSMutableSet存储已添加到新数组中的项的记录,因为NSSet查找是O(1)而不是O(N)。换句话说,无论集合中有多少元素,检查一个元素是否是NSSet的成员都需要相同的时间。使用这种方法的代码如下所示:NSMutableArray&nbsp;*unique&nbsp;=&nbsp;[NSMutableArray&nbsp;array];NSMutableSet&nbsp;*seen&nbsp;=&nbsp;[NSMutableSet&nbsp;set];for&nbsp;(id&nbsp;obj&nbsp;in&nbsp;originalArray)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(![seen&nbsp;containsObject:obj])&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[unique&nbsp;addObject:obj]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[seen&nbsp;addObject:obj]; &nbsp;&nbsp;&nbsp;&nbsp;}}不过,这看起来还是有点浪费;当问题表明原来的数组是可变的时,我们仍然在生成一个新数组,因此我们应该能够将它降到适当的位置,并节省一些内存。就像这样:NSMutableSet&nbsp;*seen&nbsp;=&nbsp;[NSMutableSet&nbsp;set];NSUInteger&nbsp;i&nbsp;=&nbsp;0;while&nbsp;(i&nbsp;<&nbsp;[originalArray&nbsp;count])&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;id&nbsp;obj&nbsp;=&nbsp;[originalArray&nbsp;objectAtIndex:i]; &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;([seen&nbsp;containsObject:obj])&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[originalArray&nbsp;removeObjectAtIndex:i]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;NB:&nbsp;we&nbsp;*don't*&nbsp;increment&nbsp;i&nbsp;here;&nbsp;since &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;we've&nbsp;removed&nbsp;the&nbsp;object&nbsp;previously&nbsp;at &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;index&nbsp;i,&nbsp;[originalArray&nbsp;objectAtIndex:i] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;now&nbsp;points&nbsp;to&nbsp;the&nbsp;next&nbsp;object&nbsp;in&nbsp;the&nbsp;array. &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[seen&nbsp;addObject:obj]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i++; &nbsp;&nbsp;&nbsp;&nbsp;}}更新Yuri Niyazov指出我的最后一个答案实际上是O(N)2)因为removeObjectAtIndex:可能在O(N)时间内运行。(他说“可能”是因为我们不确定它是如何实现的;但一个可能的实现是,在删除索引X处的对象之后,该方法循环遍历从索引X+1到数组中的最后一个对象的每个元素,然后将它们移动到前一个索引。如果是这样的话,那就是O(N)的性能。那么,该怎么办呢?这要视情况而定。如果你有一个很大的数组,而且你只需要少量的重复,那么就地去复制就可以正常工作了,这样你就不必构建一个重复的数组了。如果您有一个数组,您需要大量的重复,那么构建一个单独的、去欺骗的数组可能是最好的方法。这里的方法是,大O表示法只描述一个算法的特性,它不会确切地告诉你哪种方法对任何给定的情况都是最好的。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

iOS