回答
的NSDictionary + Merge.h
#import <Foundation/Foundation.h>
@interface NSDictionary (Merge)
+ (NSDictionary *) dictionaryByMerging: (NSDictionary *) dict1 with: (NSDictionary *) dict2;
- (NSDictionary *) dictionaryByMergingWith: (NSDictionary *) dict;
@end
的NSDictionary + Merge.m
#import "NSDictionary+Merge.h"
@implementation NSDictionary (Merge)
+ (NSDictionary *) dictionaryByMerging: (NSDictionary *) dict1 with: (NSDictionary *) dict2 {
NSMutableDictionary * result = [NSMutableDictionary dictionaryWithDictionary:dict1];
[dict2 enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) {
if (![dict1 objectForKey:key]) {
if ([obj isKindOfClass:[NSDictionary class]]) {
NSDictionary * newVal = [[dict1 objectForKey: key] dictionaryByMergingWith: (NSDictionary *) obj];
[result setObject: newVal forKey: key];
} else {
[result setObject: obj forKey: key];
}
}
}];
return (NSDictionary *) [[result mutableCopy] autorelease];
}
- (NSDictionary *) dictionaryByMergingWith: (NSDictionary *) dict {
return [[self class] dictionaryByMerging: self with: dict];
}
@end
我认为这是你在找什么:
首先,你需要做一个深层可变副本,这样你就可以NSDictionary
创建一个类来做到这一点:
@implementation NSDictionary (DeepCopy)
- (id)deepMutableCopy
{
id copy(id obj) {
id temp = [obj mutableCopy];
if ([temp isKindOfClass:[NSArray class]]) {
for (int i = 0 ; i < [temp count]; i++) {
id copied = [copy([temp objectAtIndex:i]) autorelease];
[temp replaceObjectAtIndex:i withObject:copied];
}
} else if ([temp isKindOfClass:[NSDictionary class]]) {
NSEnumerator *enumerator = [temp keyEnumerator];
NSString *nextKey;
while (nextKey = [enumerator nextObject])
[temp setObject:[copy([temp objectForKey:nextKey]) autorelease]
forKey:nextKey];
}
return temp;
}
return (copy(self));
}
@end
然后,你可以调用deepMutableCopy
这样的:
NSMutableDictionary *someDictionary = [someDict deepMutableCopy];
[someDictionary addEntriesFromDictionary:otherDictionary];
这是递归?因为NSDictionaries中的NSDictionaries也会合并? – 2010-10-25 11:17:30
我认为我们也应该取代“回归温度;”用“return [temp autorelease];”并替换“return(copy(self));”用“return [(copy(self))retain];”以避免泄漏 – AmineG 2012-02-17 10:20:48
@ someone0'-mutableCopy'暗示将所有权返还给被调用者。因此,我们不会自动发布返回值。 – 2012-02-17 11:54:50
我将此添加到上面提到的代码。它可能不完全正确,但是它处理2个字典中有1个字典不包含的元素的情况。
+ (NSDictionary *) dictionaryByMerging: (NSDictionary *) dict1 with: (NSDictionary *) dict2 {
NSMutableDictionary * result = [NSMutableDictionary dictionaryWithDictionary:dict1];
NSMutableDictionary * resultTemp = [NSMutableDictionary dictionaryWithDictionary:dict1];
[resultTemp addEntriesFromDictionary:dict2];
[resultTemp enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) {
if ([dict1 objectForKey:key]) {
if ([obj isKindOfClass:[NSDictionary class]]) {
NSDictionary * newVal = [[dict1 objectForKey: key] dictionaryByMergingWith: (NSDictionary *) obj];
[result setObject: newVal forKey: key];
} else {
[result setObject: obj forKey: key];
}
}
else if([dict2 objectForKey:key])
{
if ([obj isKindOfClass:[NSDictionary class]]) {
NSDictionary * newVal = [[dict2 objectForKey: key] dictionaryByMergingWith: (NSDictionary *) obj];
[result setObject: newVal forKey: key];
} else {
[result setObject: obj forKey: key];
}
}
}];
return (NSDictionary *) [[result mutableCopy] autorelease];
}
我知道这是一个老问题,但我需要做同样的事情:递归合并两个字典对象。我需要更进一步,合并任何可以递归合并的对象(最终目标是合并由plists创建的两个字典)。我在https://github.com/bumboarder6/NSDictionary-merge
我仍在使用该项目,但在撰写本文时,它已经可以在递归字典合并中使用(在有限的测试中)。数组和集合即将推出。
我注意到一些其他解决方案中的一些逻辑错误,我已经看到这个问题,我希望避免这些陷阱,但批评是受欢迎的。
用法很简单:
#import "NSMutableDictionary-merge.h"
NSMutableDictionary* dict1 = [NSMutableDictionary ...];
NSDictionary* dict2 = [NSDictionary ...];
[dict1 mergeWithDictionary:dict2];
我的歉意,我在阅读时被打断,看起来,我没有实际完成评论之前。 – griotspeak 2013-02-05 19:25:29
不用担心。我将继续并删除这个小交互 - 最终不完全相关:) – Mathew 2013-02-05 19:28:27
我来到这里寻找jQuery的extend
的副本,但我最终写我自己的实现。这是一个超级简单的实现,我做到了,所以我理解了一种方法来实现它。
+(NSDictionary*) dictionaryByExtending:(NSDictionary*)baseDictionary WithDictionary:(NSDictionary*)extensionDictionary {
NSMutableDictionary * resultDictionary = [NSMutableDictionary dictionaryWithDictionary:baseDictionary];
[extensionDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
BOOL isDict = [obj isKindOfClass:[NSDictionary class]];
BOOL hasValue = [baseDictionary hasObjectForKey:key] != nil;
id setObj = obj;
if(hasValue && isDict) {
BOOL hasDict = [[baseDictionary objectForKey:key] isKindOfClass:[NSDictionary class]];
if(hasDict) {
NSDictionary * extendedChildDictionary = [NSDictionary dictionaryByExtending:[baseDictionary objectForKey:key] WithDictionary:obj];
setObj = extendedChildDictionary;
}
}
[resultDictionary setObject:setObj forKey:key];
}];
return resultDictionary;
}
-(NSDictionary*) dictionaryByExtendingWithDictionary:(NSDictionary*)extensionDictionary {
return [NSDictionary dictionaryByExtending:self WithDictionary:extensionDictionary];
}
希望有人会发现这有帮助,它在我的测试与深递归工作。我正在使用它来扩展深度JSON文件。
小修改:'BOOL hasValue = [baseDictionary objectForKey:key]!= nil;'否则,效果很好。 – Rayfleck 2015-07-16 16:00:09
@Rayfleck我已经做了更新 - 谢谢 – 2015-07-20 10:35:54
#import "NSDictionary+Merge.h"
@implementation NSDictionary (Merge)
+ (NSDictionary *)dictionaryByMerging:(NSDictionary *)src with:(NSDictionary *)new
{
NSMutableDictionary *result = [src mutableCopy];
[new enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([obj isKindOfClass:[NSDictionary class]]
&& [src[key] isKindOfClass:[NSDictionary class]]) {
result[key] = [src[key] dictionaryByMergingWith:obj];
} else {
result[key] = obj;
}
}];
return [NSDictionary dictionaryWithDictionary:result];
}
- (NSDictionary *)dictionaryByMergingWith:(NSDictionary *)dict {
return [[self class] dictionaryByMerging:self with:dict];
}
@end
Alexsander Akers适用于我,除非dict2包含dict1中缺少的字典 - 它崩溃。我改变了这个逻辑:
+ (NSDictionary *) dictionaryByMerging: (NSDictionary *) dict1 with: (NSDictionary *) dict2 {
NSMutableDictionary * result = [NSMutableDictionary dictionaryWithDictionary:dict1];
[dict2 enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) {
if (![dict1 objectForKey:key]) {
[result setObject: obj forKey: key];
} else if ([obj isKindOfClass:[NSDictionary class]]) {
NSDictionary * newVal = [[dict1 objectForKey: key] dictionaryByMergingWith: (NSDictionary *) obj];
[result setObject: newVal forKey: key];
}
}];
return (NSDictionary *) [result mutableCopy];
}
因此,如果我正确读取它,那么枚举块中的逻辑是“如果'dict1'不包含'key'的对象,并且'key'的dict2'对象是字典,则将'dict1 ''把'key'的对象转换成'dict2'的'key'的对象......“但是我们已经知道'dict1'没有那个'key'的对象。因此,该块所做的就是将来自'dict2'的任何对象都不是'dict1'中的对象添加到'dict1'中。 – Mathew 2013-02-05 19:33:03
我认为你在枚举中的第一个检查是不正确的,应该删除。 'if(![dict1 objectForKey:key])'使得它在'dict2'中但不在dict1中的任何键都不会被写入。也许这是设计,但如果你想添加'dict2'中的任何唯一键,你不应该包含这个检查。 – atreat 2013-09-09 21:43:56
感谢你,虽然没有完全工作 - 我做了一个小小的改变 - 见http://stackoverflow.com/a/43172809/3346628 – pomo 2017-04-02 19:49:58