NSMutableArray 计算对象的出现次数,然后重新排列数组

Posted

技术标签:

【中文标题】NSMutableArray 计算对象的出现次数,然后重新排列数组【英文标题】:NSMutableArray counting occurrences of objects and then rearrange the array 【发布时间】:2011-06-08 09:42:20 【问题描述】:

我一直在寻找修改可以容纳同一对象的多个实例的 NSMutableArray 的最佳方法。我也为 4.0 以下的 ios 版本工作,所以使用块不是要走的路。

情况如下:

我有一个这样的数组:

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

假设object2 object3 和object4 实际上是同一个对象。对象 1 和对象 7 也是如此。然后我想重新排列数组,以便最先出现,依此类推。所以数组必须看起来像这样:

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

【问题讨论】:

当您有两个“组”大小相同的对象时,您期望什么行为?说object2,object3,object4是同一个object,object1,object7,object8是同一个object。既然这两个对象出现次数最多,那么它们对应的数组元素在结果数组中是否需要连续? 【参考方案1】:

有几种方法可以做到这一点,其中一种是使用辅助 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];
    

【讨论】:

这听起来是个好主意,但还不够。它会混淆对象,因为有多个集合具有相同数量的多个对象。 OP 需要确定他们希望如何对具有相同计数的对象组进行排序,并将其合并到排序方法中。 @extr 啊,真的!我会就这个问题发表评论。【参考方案2】:

您需要的是NSBag, by Erica Sadun (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

【讨论】:

【参考方案3】:

您可以使用 isKindOfClass 和 isMemberOfClass 实例方法来管理它。因此,只需循环遍历您的数组并根据您的要求继续将项目推送到新数组中

【讨论】:

以上是关于NSMutableArray 计算对象的出现次数,然后重新排列数组的主要内容,如果未能解决你的问题,请参考以下文章

如何计算 JQ 中每个对象的键值对的出现次数?

递归计算对象在字符串中出现的次数

如何计算指向不同向量数组中特定对象的指针的出现次数

Power BI DAX 度量:考虑视觉对象的筛选上下文,计算列中值的出现次数

计算 json 对象中键的出现次数 - IMPALA/HIVE

是否可以计算每个键在 JSON 列中出现的次数?