NSMutableArray 计算对象的出现次数并重新排列数组

5

我一直在寻找修改NSMutableArray的最佳方法,该数组可以容纳多个相同对象的实例。我还为iOS 4.0以下版本工作,因此使用块不是正确的方法。

这是情况:

我有一个像这样的数组:

ARRAY = [object1,object2,object3,object4,object5,object6,object7,object8];

假设object2,object3和object4实际上是相同的对象。object1和object7也是如此。那么我想重新排列数组,使出现最多的对象首先出现,以此类推。因此,数组应该像这样:
[object2,object3,object4,object1,object7,object5,object6,object8];
请注意保留原有的HTML标签。

当您有两个大小相同的“组”对象时,您期望什么行为?假设object2、object3、object4是同一个对象,而object1、object7、object8是同一个对象。由于这两个对象具有最多的出现次数,它们对应的数组元素是否需要在结果数组中连续? - user557219
3个回答

6

有几种方法可以做到这一点,其中之一是使用辅助的 NSCountedSet 实例和一个使用该 NSCountedSet 进行比较的函数:

NSInteger countedSort(id obj1, id obj2, void *context) {
    NSCountedSet *countedSet = context;
    NSUInteger obj1Count = [countedSet countForObject:obj1];
    NSUInteger obj2Count = [countedSet countForObject:obj2];

    if (obj1Count > obj2Count) return NSOrderedAscending;
    else if (obj1Count < obj2Count) return NSOrderedDescending;
    return NSOrderedSame;
}

并且

NSMutableArray *array = …;

NSCountedSet *countedSet = [[[NSCountedSet alloc] initWithArray:array]
    autorelease];

[array sortUsingFunction:countedSort context:countedSet];
编辑: extremeboredom巧妙地发现,如果两个不同的对象有相同的重复次数,则它们对应的元素在结果数组中不一定是连续的。这种解决方案只应在不需要将相同对象连续的情况下使用。 进一步编辑: 如果您需要表示同一对象的元素连续,可以创建一个仅包含不同元素且按重复计数排序的较小数组。然后,创建另一个按重复计数排序的元素数组。根据您的需求,您实际上可能不需要结果数组 - 可能只需要distinctArray和计数集。
NSMutableArray *array = …;
NSCountedSet *countedSet = [[[NSCountedSet alloc] initWithArray:array]
    autorelease];

// Array with distinct elements only, sorted by their repeat count
NSArray *distinctArray = [[countedSet allObjects]
    sortedArrayUsingFunction:countedSort context:countedSet];

// Array with all the elements, where elements representing the same
// object are contiguous
NSMutableArray *sortedArray = [NSMutableArray arrayWithCapacity:[array count]];
for (id object in distinctArray) {
    for (NSUInteger i = 0; i < [countedSet countForObject:object]; i++) {
        [sortedArray addObject:object];
    }
}

这听起来是个不错的想法,但还不够。如果有多个包含相同数量对象的集合,它会混淆对象。原始帖子需要确定他们想如何对具有相同计数的对象组进行排序,并将其纳入排序方法中。 - extremeboredom
@extr 啊,说得对!我会在问题下面发表评论。 - user557219

1
你所需要的是 Erica Sadun开发的NSBag(GitHub)。一个简单的使用案例:
NSArray *objArray = @[ @"a", @"a", @"b", @"B", @"c", @"cc", @"c"];      
NSBag       *aBag = NSBag.new;

for ( id thing in objArray )     [aBag add:thing];   // fill the bag

for ( id unique in aBag.objects )                    // count'em out
         NSLog(   @"%@,     %i", 
                  unique,   [aBag occurrencesOf:unique] );

输出:

cc, 1
b, 1
B, 1
c, 2
a, 2

0

你可以通过使用isKindOfClass和isMemberOfClass实例方法来管理此问题。因此,只需遍历数组并根据要求不断向新数组中添加项目即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接