代码之家  ›  专栏  ›  技术社区  ›  Alexsander Akers

深度合并nsDictionaries

  •  15
  • Alexsander Akers  · 技术社区  · 14 年前

    我要合并两个 NSDictionary 如果字典中有字典,它们也会合并。

    或多或少像jquery的 extend 功能。

    7 回复  |  直到 6 年前
        1
  •  30
  •   johnyu    10 年前

    nsdictionary+合并.h

    #import <Foundation/Foundation.h>
    
    @interface NSDictionary (Merge)
    
    + (NSDictionary *) dictionaryByMerging: (NSDictionary *) dict1 with: (NSDictionary *) dict2;
    - (NSDictionary *) dictionaryByMergingWith: (NSDictionary *) dict;
    
    @end
    

    nsdictionary+合并.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
    
        2
  •  7
  •   Jacob Relkin    13 年前

    我想这就是你要找的:

    首先,你需要 深可变拷贝 ,以便您可以在 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];
    
        3
  •  4
  •   ucangetit    13 年前

    我在上面提到的代码中添加了这个。它可能不完全正确,但它处理的情况是2 dict有一个元素,而1 dict没有。

    + (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];
    

    }

        4
  •  1
  •   Hugo Scott-Slade    10 年前

    我来这里是想找一份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文件。

        5
  •  0
  •   Mathew    12 年前

    我知道这是一个老问题,但我需要做同样的事情:递归地合并两个字典对象。我需要更进一步,合并任何可以递归合并的对象(最终目标是合并从plist创建的两个字典)。我的解决方案托管在 https://github.com/bumboarder6/NSDictionary-merge

    我仍在研究这个项目,但在撰写本文时,它已经可以(在有限的测试中)进行递归字典合并。数组和集合即将到来。

    我注意到在我为这个问题所看到的其他一些解决方案中有一些逻辑错误,我希望能避免这些陷阱,但欢迎批评。

    用法很简单:

    #import "NSMutableDictionary-merge.h"
    
    NSMutableDictionary* dict1 = [NSMutableDictionary ...];
    NSDictionary* dict2 = [NSDictionary ...];
    
    [dict1 mergeWithDictionary:dict2];
    
        6
  •  0
  •   tuoxie007    8 年前
    #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
    
        7
  •  0
  •   pomo    8 年前

    AlexsanderAkers为我工作,除了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];
    }