合并字典 - 不兼容的类型错误

时间:2013-01-14 23:10:33

标签: ios objective-c nsdictionary

我一直试图将两个NSDictionaries合并几个小时。搜索并发现我可以使用[NSMutableDictionary addEntriesFromDictionary:]

    NSDictionary *areaAttributes = [[area entity] attributesByName];
    NSDictionary *gpsAttributes = [[gps entity] attributesByName];

    NSMutableDictionary *areaAttributesM = [areaAttributes mutableCopy];
    NSMutableDictionary *gpsAttributesM = [gpsAttributes mutableCopy];

    NSMutableDictionary *combinedAttributes =  [areaAttributesM addEntriesFromDictionary:gpsAttributesM];

但我收到错误:

Initializing 'NSMutableDictionary *_strong' with an expression of incompatible type 'void'

所以这是说[areaAttributesM addEntriesFromDictionary:gpsAttributesM]返回void?我的理解是否正确?为什么它回归无效?

2 个答案:

答案 0 :(得分:13)

是的,你是对的。来自the docs

- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary

至于为什么,这很简单:在Cocoa中改变对象的函数通常会返回void,因此您可以轻松地将它们与返回不同对象的函数区分开来。

此外,没有理由mutableCopy gpsAttributes字典;它只是被用作-[addEntriesFromDictionary:]的参数,它不需要是可变的。

所以,正确的方法是:

NSDictionary *areaAttributes = [[area entity] attributesByName];
NSDictionary *gpsAttributes = [[gps entity] attributesByName];

NSMutableDictionary *combinedAttributes = [areaAttributes mutableCopy];
[combinedAttributes addEntriesFromDictionary:gpsAttributes];

如果您经常这样做,您可能希望将其包装在函数(或NSDictionary类别中的方法)中:

NSDictionary *mergeDictionaries(NSDictionary *lhs, NSDictionary *rhs) {
    NSMutableDictionary *ret = [lhs mutableCopy];
    [ret addEntriesFromDictionary:rhs];
    return ret;
}

答案 1 :(得分:0)

在文档中,addEntriesFromDictionary告诉:

如果两个词典都包含相同的键,则接收字典的该键的先前值对象将发送一个释放消息,新值对象将取代它。 您需要使用setObject将每个对象添加到字典中.YOu需要遍历一个字典的键并将其添加到最终字典中。

即使是setObject也是这样说的:

价值的关键。密钥被复制(使用copyWithZone:;密钥必须符合NSCopying协议)。如果字典中已存在aKey,则anObject取代它。 字典中不能有两个相同的键。字典中的所有键都是唯一的。

如果您仍想在字典中使用相同的键值,则必须使用其他键。

例如,您有两个带有以下值的词典:

NSDictionary *dict1=@{@"hello":@"1",@"hello2" :@"2"};
NSDictionary *dict2=@{@"hello":@"1",@"hello2":@"2",@"hello3":@"1",@"hello6":@"2",@"hello4":@"1",@"hello5" :@"2"};

 NSMutableDictionary *mutableDict=[NSMutableDictionary dictionaryWithDictionary:dict1];
    for (id key in dict2.allKeys){
        for (id subKey in dict1.allKeys){
            if (key==subKey) {
                [mutableDict setObject:dict2[key] forKey:[NSString stringWithFormat:@"Ext-%@",key]];
            }else{
                [mutableDict setObject:dict2[key] forKey:key];
            }
        }
    }

并且在此循环结束时,您的新可变字典将具有以下关键值:

{
    "Ext-hello" = 1;
    "Ext-hello2" = 2;
    hello = 1;
    hello2 = 2;
    hello3 = 1;
    hello4 = 1;
    hello5 = 2;
    hello6 = 2;
}

如您所见,hello和hello2键被重命名为Ext-hello1,Ext-hello2。形成dict1,你仍然将所有dict2值添加到你的可变字典中。

如果您不想添加新密钥,则可以将值添加到arrya中并将该数组添加到字典中。你可以将for循环修改为:

for (id key in dict2.allKeys){
    for (id subKey in dict1.allKeys){
        if (key==subKey) {
            NSMutableArray *myArr=[[NSMutableArray alloc]init];
            [myArr addObject:dict1[subKey]];
            [myArr addObject:dict2[key]];
            [mutableDict setObject:myArr forKey:key];
        }else{
            [mutableDict setObject:dict2[key] forKey:key];
        }
    }
}

现在您将值合并到一个数组中:

{
    hello =     (
        1,
        1
    );
    hello2 = 2;
    hello3 = 1;
    hello4 = 1;
    hello5 = 2;
    hello6 = 2;
}

这样,键的数量将相同,同一键的值将作为数组添加。