9

この質問はこの質問に似ていますが、この方法は辞書のルートレベルでのみ機能します。

出現するNSNull値を空の文字列に置き換えて、辞書全体をplistファイルに保存できるようにします(NSNullを追加すると、ファイルは書き込まれません)。

しかし、私の辞書にはネストされた辞書があります。このような:

"dictKeyName" = {
    innerStrKeyName = "This is a string in a dictionary";
    innerNullKeyName = "<null>";
    innerDictKeyName = {
        "innerDictStrKeyName" = "This is a string in a Dictionary in another Dictionary";
        "innerDictNullKeyName" = "<null>";
    };
};

私が使用する場合:

@interface NSDictionary (JRAdditions)
- (NSDictionary *) dictionaryByReplacingNullsWithStrings;
@end

@implementation NSDictionary (JRAdditions)

- (NSDictionary *) dictionaryByReplacingNullsWithStrings {

    const NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:self];
    const id nul = [NSNull null];
    const NSString *blank = @"";

    for(NSString *key in replaced) {
        const id object = [self objectForKey:key];
        if(object == nul) {
            [replaced setObject:blank forKey:key];
        }
    }
    return [NSDictionary dictionaryWithDictionary:replaced];
}

@end

私はこのようなものを手に入れます:

"dictKeyName" = {
    innerStrKeyName = "This is a string in a dictionary";
    innerNullKeyName = ""; <-- this value has changed
    innerDictKeyName = {
        "innerDictStrKeyName" = "This is a string in a Dictionary in another Dictionary";
        "innerDictNullKeyName" = "<null>"; <-- this value hasn't changed
    };
};

NSNullネストされた辞書を含むすべての辞書からすべての値を見つける方法はありますか...?

編集: データはJSONフィードから取得されているため、受け取るデータは動的です(フィードが変更されるたびにアプリを更新する必要はありません)。

4

8 に答える 8

17

メソッドを少し変更すると、再帰的になる可能性があります。

@interface NSDictionary (JRAdditions)
- (NSDictionary *) dictionaryByReplacingNullsWithStrings;
@end

@implementation NSDictionary (JRAdditions)

- (NSDictionary *) dictionaryByReplacingNullsWithStrings {
    const NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary: self];
    const id nul = [NSNull null];
    const NSString *blank = @"";

    for (NSString *key in self) {
        const id object = [self objectForKey: key];
        if (object == nul) {
            [replaced setObject: blank forKey: key];
        }
        else if ([object isKindOfClass: [NSDictionary class]]) {
            [replaced setObject: [(NSDictionary *) object dictionaryByReplacingNullsWithStrings] forKey: key];
        }
    }
    return [NSDictionary dictionaryWithDictionary: replaced];
}

self代わりに高速列挙がオンになっていることに注意してくださいreplaced

上記のコードでは、この例は次のとおりです。

NSMutableDictionary *dic1 = [NSMutableDictionary dictionary];
[dic1 setObject: @"string 1" forKey: @"key1.1"];
[dic1 setObject: [NSNull null] forKey: @"key1.2"];

NSMutableDictionary *dic2 = [NSMutableDictionary dictionary];
[dic2 setObject: @"string 2" forKey: @"key2.1"];
[dic2 setObject: [NSNull null] forKey: @"key2.2"];

[dic1 setObject: dic2 forKey: @"key1.3"];

NSLog(@"%@", dic1);
NSLog(@"%@", [dic1 dictionaryByReplacingNullsWithStrings]);

この結果をレンダリングします:

2012-09-01 08:30:16.210 Test[57731:c07] {
    "key1.1" = "string 1";
    "key1.2" = "<null>";
    "key1.3" =     {
        "key2.1" = "string 2";
        "key2.2" = "<null>";
    };
}
2012-09-01 08:30:16.212 Test[57731:c07] {
    "key1.1" = "string 1";
    "key1.2" = "";
    "key1.3" =     {
        "key2.1" = "string 2";
        "key2.2" = "";
    };
于 2012-08-31T11:15:47.167 に答える
10

ネストされたループを使用して、NSArray を含む辞書全体ですべての NULL を nil に置き換えました。

- (NSDictionary *) dictionaryByReplacingNullsWithNil:(NSDictionary*)sourceDictionary {

    NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:sourceDictionary];
    const id nul = [NSNull null];

    for(NSString *key in replaced) {
        const id object = [sourceDictionary objectForKey:key];
        if(object == nul) {
            [replaced setValue:nil forKey:key];
        }
    }
    return [NSDictionary dictionaryWithDictionary:replaced];
}

-(NSDictionary *) nestedDictionaryByReplacingNullsWithNil:(NSDictionary*)sourceDictionary
{
    NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:sourceDictionary];
    const id nul = [NSNull null];
    const NSString *blank = @"";
    [sourceDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
        object = [sourceDictionary objectForKey:key];
        if([object isKindOfClass:[NSDictionary class]])
        {
            NSDictionary *innerDict = object;
            [replaced setObject:[self nestedDictionaryByReplacingNullsWithNil:innerDict] forKey:key];

        }
        else if([object isKindOfClass:[NSArray class]]){
            NSMutableArray *nullFreeRecords = [NSMutableArray array];
            for (id record in object) {

                if([record isKindOfClass:[NSDictionary class]])
                {
                    NSDictionary *nullFreeRecord = [self nestedDictionaryByReplacingNullsWithNil:record];
                    [nullFreeRecords addObject:nullFreeRecord];
                }
            }
            [replaced setObject:nullFreeRecords forKey:key];
        }
        else
        {
            if(object == nul) {
                [replaced setObject:blank forKey:key];
            }
        }
    }];

    return [NSDictionary dictionaryWithDictionary:replaced];  
}
于 2013-03-21T08:04:47.183 に答える
2

Swift 1.2でこれが必要な場合のために、スニペットは次のとおりです。

class func removeNullsFromDictionary(origin:[String:AnyObject]) -> [String:AnyObject] {
    var destination:[String:AnyObject] = [:]
    for key in origin.keys {
        if origin[key] != nil && !(origin[key] is NSNull){
            if origin[key] is [String:AnyObject] {
                destination[key] = self.removeNullsFromDictionary(origin[key] as! [String:AnyObject])
            } else if origin[key] is [AnyObject] {
                let orgArray = origin[key] as! [AnyObject]
                var destArray: [AnyObject] = []
                for item in orgArray {
                    if item is [String:AnyObject] {
                        destArray.append(self.removeNullsFromDictionary(item as! [String:AnyObject]))
                    } else {
                        destArray.append(item)
                    }
                }
                destination[key] = destArray
            } else {
                destination[key] = origin[key]
            }
        } else {
            destination[key] = ""
        }
    }
    return destination
}
于 2015-08-31T19:51:43.587 に答える
2

次の方法は、任意の数のネストされた辞書の配列に対して完全に機能します。

- (NSMutableDictionary *)dictionaryByReplacingNullsWithStrings:(NSDictionary *)jobList
{
    NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:jobList];
    const id nul = [NSNull null];
    const NSString *blank = @"";

    for (NSString *key in [replaced allKeys])
    {
        id object = [replaced objectForKey:key];
        if (object == nul)
        {
            [replaced setObject:blank
                         forKey:key];
        }
        else
        if ([object isKindOfClass:[NSDictionary class]])
        {
            [replaced setObject:[self replaceNullInNested:object]
                         forKey:key];
        }
        else
        if ([object isKindOfClass:[NSArray class]])
        {
            NSMutableArray *dc = [[NSMutableArray alloc] init];
            for (NSDictionary *tempDict in object)
            {
                [dc addObject:[self dictionaryByReplacingNullsWithStrings:tempDict]];
            }
            [replaced setObject:dc
                         forKey:key];
        }
    }
    return replaced;
}

- (NSMutableDictionary *)replaceNullInNested:(NSDictionary *)targetDict
{
    // make it to be NSMutableDictionary in case that it is nsdictionary
    NSMutableDictionary *m = [targetDict mutableCopy];
    NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:m];
    const id nul = [NSNull null];
    const NSString *blank = @"";

    for (NSString *key in [replaced allKeys])
    {
        const id object = [replaced objectForKey:key];
        if (object == nul)
        {
            [replaced setObject:blank
                         forKey:key];
        }
        else
        if ([object isKindOfClass:[NSArray class]])
        {
//            NSLog(@"found null inside and key is %@", key);
            // make it to be able to set value by create a new one
            NSMutableArray *a = [object mutableCopy];
            for (int i = 0; i < [a count]; i++)
            {
                for (NSString *subKey in [[a objectAtIndex:i] allKeys])
                {
                    if ([[object objectAtIndex:i] valueForKey:subKey] == nul)
                    {
                        [[object objectAtIndex:i] setValue:blank
                                                    forKey:subKey];
                    }
                }
            }
            // replace the updated one with old one
            [replaced setObject:a
                         forKey:key];
        }
    }
    return replaced;
}

必要な機能に従って、上記の変更された方法を使用しました。

// メソッドを呼び出す

NSMutableDictionary *sortedDict = [[NSMutableDictionary alloc] init];

for (NSString *key in jobList){
    NSMutableArray *tempArray = [[NSMutableArray alloc] init];

    for (NSDictionary *tempDict in [jobList objectForKey:key])
    {
        [tempArray addObject:[self dictionaryByReplacingNullsWithStrings:tempDict]];
    }
    [sortedDict setObject:tempArray forKey:key];
}
于 2015-11-02T11:52:07.303 に答える
0

これを試して:

@interface NSDictionary (JRAdditions)
 - (NSDictionary *) dictionaryByReplacingNullsWithStrings;
 -(NSDictionary *) nestedDictionaryByReplacingNullsWithStrings;
@end

@implementation NSDictionary (JRAdditions)

- (NSDictionary *) dictionaryByReplacingNullsWithStrings {

const NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:self];
const id nul = [NSNull null];
const NSString *blank = @"";

for(NSString *key in replaced) {
    const id object = [self objectForKey:key];
    if(object == nul) {
        [replaced setObject:blank forKey:key];
    }
}
return [NSDictionary dictionaryWithDictionary:replaced];
}

-(NSDictionary *) nestedDictionaryByReplacingNullsWithStrings
{  
  const NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:self];
  const id nul = [NSNull null];
  const NSString *blank = @"";
  for(id *item in replaced) {
    const id object = [self objectForKey:key];
    if([object isKindofClass:[NSDictionary class]])
    {
       NSDictionary *innerDict = object;
       [replaced setObject:[innerDict dictionaryByReplacingNullsWithStrings] forKey:key];

    }
    else
    {
     if(object == nul) {
        [replaced setObject:blank forKey:key];
     }
    }
 }
 return [NSDictionary dictionaryWithDictionary:replaced];  
}
于 2012-08-31T11:30:25.153 に答える
0

このソリューションは、配列と辞書、およびネストされた配列と辞書など (再帰的に) で機能します。

- (NSDictionary *)writableDictionary:(NSDictionary *)dictionary
{
    NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionary];

    for (id key in mutableDictionary.allKeys)
    {
        id value = mutableDictionary[key];
        mutableDictionary[key] = [self writableValue:value];
    }

    return mutableDictionary;
}

- (NSArray *)writableArray:(NSArray *)array
{
    NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array];

    for (int i = 0; i < mutableArray.count; ++i)
    {
        id value = mutableArray[i];
        mutableArray[i] = [self writableValue:value];
    }

    return mutableArray;
}

- (id)writableValue:(id)value
{
    if ([value isKindOfClass:[NSNull class]])
    {
        value = @"";
    }
    else if ([value isKindOfClass:[NSDictionary class]])
    {
        value = [self writableDictionary:value];
    }
    else if ([value isKindOfClass:[NSArray class]])
    {
        value = [self writableArray:value];
    }
    return value;
}
于 2014-10-24T13:23:55.547 に答える
0

このコード

@interface NSDictionary (JRAdditions)
    - (NSDictionary *) dictionaryByReplacingNullsWithStrings;
@end

Monkey は NSDictionary にパッチを適用します。つまり、dictionaryByReplaceing... をルートだけでなく、ネストされた辞書でも好きなように呼び出すことができます。

設計の観点からこれに同意することはできませんが、問題は解決します。

于 2012-08-31T11:03:36.797 に答える
0

辞書に配列がある場合、上記の回答は状況に対応していません。これをチェックしてください

+(NSMutableDictionary*)getValuesWithOutNull:(NSDictionary          
     *)yourDictionary{
       NSMutableDictionary *replaced = [NSMutableDictionary 
     dictionaryWithDictionary: yourDictionary];
      id nul = [NSNull null];
      NSString *blank = @"";

for (NSString *key in yourDictionary) {
    const id object = [yourDictionary objectForKey: key];
    if (object == nul) {
        [replaced setObject: blank forKey: key];
    }
    else if ([object isKindOfClass: [NSDictionary class]]) {
        [replaced setObject:[self getValuesWithOutNull:object] 
forKey:key];
    }
    else if([object isKindOfClass: [NSArray class]])
    {
        NSMutableArray *array  = [NSMutableArray 
arrayWithArray:object];
        for(int i = 0 ;i < array.count;i++)
        {
            NSDictionary *dict = [array objectAtIndex:i];
            [array replaceObjectAtIndex:i withObject:[self 
  getValuesWithOutNull:dict]];
        }
        [replaced setObject:array forKey:key];
    }
 }
  return  replaced;

}
于 2015-07-22T17:49:57.037 に答える