回答
的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];
}
- 1. 結合NSDictionaries
- 2. 如何結合兩個NSDictionaries?
- 3. 提取深層XML結構
- 4. 具有適合DDD的深層次結構的聚合根?
- 5. 如何深度複製NSDictionaries的NSArray?
- 6. 結合深泛型集合
- 7. 動態-shallow結合和深結合
- 8. C指針結構的深層副本
- 9. 使用RESTKit解析深層XML結構
- 10. 使用Java訪問深層XML結構
- 11. 不變JS更新深層結構
- 12. Perl單元測試深層結構
- 13. MDX結合層次
- 14. NSDictionaries
- 15. 淺層和深層複製
- 16. 我需要將兩個NSArray/NSDictionaries結合在一起
- 17. 處理繼承層次結構3層深jpa
- 18. 深層繼承層次結構的替代方法?
- 19. MvvmCross +深層鏈接
- 20. Laravel深層關係
- 21. 深層鏈接ERR_UNKNOWN_URL_SCHEME
- 22. Google+深層鏈接
- 23. Firebase深層查詢
- 24. Sinatra:疊層太深
- 25. Ajax深層鏈接?
- 26. 層次結構的集合
- 27. CALayer面具 - 結合兩層
- 28. 結合MVVM和N層體系結構
- 29. Knockout.js ko.applyBindings()層次結構結合
- 30. HtmlPanelGroup - 結合 - H:樹panelGroup中深入
因此,如果我正確讀取它,那麼枚舉塊中的邏輯是「如果'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