使用自定义对象从数组构建不可变NSDictionary,其中每个键可以有多个对象

时间:2013-08-22 19:45:35

标签: ios nsmutabledictionary

我试图查找这个问题,但没有运气,我想构建一个函数,创建一个键和对象的“不可变字典”,其中对象也是一个不可变数组。

我将传递给这个函数的是我创建的一个对象数组,每个对象都有一个key属性,我想用它来对字典中的对象进行分组。

我想出了这个,我测试了它并且它有效,但我想看看是否有更好/更安全的方法来做到这一点。

我确实使用ARC,我想确保当我从函数返回时,每个东西都是不可变的。

- (NSDictionary* )testFunction:(NSArray *)arrayOfObjects
{
    NSMutableDictionary *tmpMutableDic = [[NSMutableDictionary alloc] init];

    for(MyCustomObject *obj in arrayOfObjects)
    {
        if ([tmpMutableDic objectForKey:obj.key] == nil)
        {
            // First time we get this key. add key/value paid where the value is immutable array
            [tmpMutableDic setObject:[NSArray arrayWithObject:obj] forKey:obj.key];
        }
        else
        {
            // We got this key before so, build a Mutable array from the existing immutable array and add the object then, convert it to immutable and store it back in the dictionary.
            NSMutableArray *tmpMutableArray = [NSMutableArray arrayWithArray:[tmpMutableDic objectForKey:obj.key]];
            [tmpMutableArray addObject:obj];
            [tmpMutableDic setObject:[tmpMutableArray copy] forKey:obj.key];
        }
    }

   // Return an immutable version of the dictionary.
   return [tmpMutableDic copy];
}

2 个答案:

答案 0 :(得分:2)

我认为这是很多复制。我要等到最后将可变数组转换为不可变数组,而不是每次要添加元素时都将其复制:

- (NSDictionary *)testFunction:(NSArray *)arrayOfObjects
{
    NSMutableDictionary *tmpMutableDic = [[NSMutableDictionary alloc] init];

    for(MyCustomObject *obj in arrayOfObjects)
    {
        if ([tmpMutableDic objectForKey:obj.key] == nil)
        {
            // First time we got this key, add array
            [tmpMutableDic setObject:[[NSMutableArray alloc] init] forKey:obj.key];
        }
        // Add the object
        [[tmpMutableDic objectForKey:obj.key] addObject:obj];
    }

    // Convert mutable arrays to immutable
    for (NSString *key in tmpMutableDic.allkeys) {
        [tmpMutableDic setObject:[[tmpMutableDic objectForKey:key] copy] forKey:key];
    }

    // Return an immutable version of the dictionary.
    return [tmpMutableDic copy];
}

答案 1 :(得分:0)

没有内置的一对多字典的概念,所以我认为没有一种更简洁的方法来实现你所写的内容 - 当然没有一行语法就像其他一大堆字体一样常见的操纵。

那就是说,小的建议是:

使用键值编码来读取键控属性。因此,只需调用obj.key即可将[obj valueForKeyPath:keyPath]的引用替换为keyPath,并将obj.key作为参数。然后你只需要编写一次这段代码。

为安全起见,您应检查nil是否[tmpMutableDic setObject:... forKey:nil]。如果是,那么您最终会执行nil,这会引发异常,因为词典无法针对copy键存储值。

copy将返回一个不可变的字典,但其中的值仍然是可变数组,因为副本很浅。如果你明确想要返回不可变数组,你需要编写一个稍微深一点的复制函数。

此时您可能会发现您更愿意切换到基于密钥对传入阵列进行排序的算法,然后在每次密钥值更改时逐步创建新阵列。这样做的好处是你总是知道你完成一个数组的那一刻,这样你就可以将{{1}}存储到字典中,然后在稍后删除稍微深一些的副本,尽管代价是一种。