2

一連のカテゴリにたくさんのオブジェクトがあります。各カテゴリーがいくつあるのか知りたいのですが。

別の言語では、辞書を作成してから、オブジェクトを反復処理し、各オブジェクトの辞書の適切な値をインクリメントします。ただし、Objective-CのNSDictionaryにネイティブの数値タイプを保存できないため、NSNumberと数値タイプの間で絶えず変換を行っています。

NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
for (MyObject *obj in objs) {  
    NSNumber *old = [dictionary objectForKey:obj.category];
    NSNumber *new = [NSNumber numberWithInteger:1 + old.integerValue];
    [dictionary setObject:new forKey:obj.category];
}

これを行うためのより効率的な方法はありますか?

4

4 に答える 4

1

NSMutableData を使用してカウンターを保存できます。

int                 * count;
NSMutableData       * num;
NSMutableDictionary * dictionary;

dictionary = [[NSMutableDictionary alloc] init];

for (MyObject *obj in objs)
{
    if ((count = [[dictionary objectForKey:obj.category] mutableBytes]) == nil)
    {
        num    = [NSMutableData dataWithCapacity:sizeof(int)];
        count  = [num mutableBytes];
        *count = 0;
        [dictionary setObject:num forKey:obj.category];
    };
    *count += 1;
};

NSNumberこれにより、カテゴリのカウントが更新されるたびに辞書が変更されたり、新しい辞書が割り当てられたりするのを防ぎます。

于 2012-07-02T20:27:59.537 に答える
0

それが本当にボトルネックである場合は、NSMutableDictionary の代わりに基礎となる CFDictionaryRef を使用して、整数を NSNumber 値でボックス化する代わりに直接格納する辞書を作成できます。

詳細については、 CFDictionaryCreateMutable および CFDictionaryValueCallBacks のドキュメントを参照してください。ただし、基本的な考え方は、retain と release は何も行わず、説明はオンザフライで NSNumber を生成し (または単に stringWithFormat:"%d" を実行します)、equal は int を比較するというものです。直接。

コードのトリッキーな部分を示すサンプルを次に示します。

#import <CoreFoundation/CoreFoundation.h>
#import <Foundation/Foundation.h>

CFStringRef intdesc(const void *value) {
  int i = (int)value;
  CFNumberRef n = CFNumberCreate(NULL, kCFNumberIntType, &i);
  CFStringRef s = CFCopyDescription(n);
  CFRelease(n);
  return s;
}

Boolean inteq(const void *value1, const void *value2) {
  int i1 = (int)value1, i2 = (int)value2;
  return i1 == i2;
}

int main(int argc, char *argv[]) {
  CFDictionaryValueCallBacks cb = { 0, NULL, NULL, &intdesc, &inteq };

  CFMutableDictionaryRef d = 
    CFDictionaryCreateMutable(NULL,
              0,
              &kCFTypeDictionaryKeyCallBacks,
              &cb);
  CFDictionarySetValue(d, @"Key1", (void *)1);
  CFDictionarySetValue(d, @"Key2", (void *)2);
  CFStringRef s = CFCopyDescription(d);
  NSLog(@"%@", s);
  CFRelease(s);
  CFRelease(d);
  return 0;
}

これをたくさん行う場合は、おそらく ObjC でまとめる必要がありますが (特に ARC を使用している場合)、これは読者の演習として残します。

于 2012-07-02T20:32:03.473 に答える