13 Stimmen

Ersetzen aller NSNull-Objekte in einem NSDictionary

Ich bin neugierig, ich habe derzeit eine NSDictionary wobei einige Werte auf einen NSNull Objekt dank der Hilfe von json-framework.

Das Ziel ist es, alle NSNull Werte und ersetzen sie durch eine leere Zeichenkette.

Ich bin sicher, jemand hat das schon einmal gemacht? Kein Zweifel, es ist wahrscheinlich ein Vierzeiler und ist einfach, ich bin einfach viel zu ausgebrannt, um dies auf eigene Faust herauszufinden.

44voto

Stakenborg Punkte 2850

Ich habe ein paar Änderungen an Jacobs ursprünglicher Antwort vorgenommen, um sie so zu erweitern, dass sie mit Wörterbüchern und Arrays umgehen kann, die innerhalb des ursprünglichen Wörterbuchs gespeichert sind.

#import "NSDictionary+NullReplacement.h"
#import "NSArray+NullReplacement.h"

@implementation NSDictionary (NullReplacement)

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

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

@end

Und natürlich gibt es auch eine Kategorie "Array":

#import "NSArray+NullReplacement.h"
#import "NSDictionary+NullReplacement.h"

@implementation NSArray (NullReplacement)

- (NSArray *)arrayByReplacingNullsWithBlanks  {
    NSMutableArray *replaced = [self mutableCopy];
    const id nul = [NSNull null];
    const NSString *blank = @"";
    for (int idx = 0; idx < [replaced count]; idx++) {
        id object = [replaced objectAtIndex:idx];
        if (object == nul) [replaced replaceObjectAtIndex:idx withObject:blank];
        else if ([object isKindOfClass:[NSDictionary class]]) [replaced replaceObjectAtIndex:idx withObject:[object dictionaryByReplacingNullsWithBlanks]];
        else if ([object isKindOfClass:[NSArray class]]) [replaced replaceObjectAtIndex:idx withObject:[object arrayByReplacingNullsWithBlanks]];
    }
    return [replaced copy];
}

@end

Damit können Sie ein beliebiges Array oder Wörterbuch nehmen und rekursiv alle [NSNull null]-Instanzen löschen.

P.S. Der Vollständigkeit halber sind hier die Header-Dateien:

@interface NSDictionary (NullReplacement)

- (NSDictionary *)dictionaryByReplacingNullsWithBlanks;

@end

Und die Kopfzeile des Arrays:

@interface NSArray (NullReplacement)

- (NSArray *)arrayByReplacingNullsWithBlanks;

@end

16voto

Jacob Relkin Punkte 156445

Ganz einfach:

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

@implementation NSDictionary (JRAdditions)

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

   for(NSString *key in self) {
      const id object = [self objectForKey:key];
      if(object == nul) {
         //pointer comparison is way faster than -isKindOfClass:
         //since [NSNull null] is a singleton, they'll all point to the same
         //location in memory.
         [replaced setObject:blank 
                      forKey:key];
      }
   }

   return [replaced copy];
}

@end

使用することです:

NSDictionary *someDictThatHasNulls = ...;
NSDictionary *replacedDict = [someDictThatHasNulls dictionaryByReplacingNullsWithStrings];

6voto

Das Wörterbuch auf der Suche nach NSNull zu durchforsten ist eine Möglichkeit, das Problem anzugehen, aber ich habe einen etwas fauleren Ansatz gewählt. Anstelle von nil könnten Sie eine leere Zeichenfolge zuweisen, aber das Prinzip ist das gleiche.

CPJSONDictionary.h

@interface NSDictionary (CPJSONDictionary)
- (id)jsonObjectForKey:(id)aKey;
@end

CPJSONDictionary.m

@implementation NSDictionary (CPJSONDictionary)

- (id)jsonObjectForKey:(id)aKey {
    id object = [self objectForKey:aKey];
    if ([object isKindOfClass:[NSNull class]]) {
        object = nil;
    }

    return object;
}

@end

4voto

Eva Madrazo Punkte 4721

Ich habe die Stakenborg-Lösung getestet. Sie funktioniert gut, aber sie hat folgendes Problem. Wenn ein Objekt erwartet wird, um eine Zahl zu sein, zum Beispiel, konvertieren es in NSNull kann eine Fehlerquelle sein. Ich habe eine neue Methode zum direkten Entfernen der NSNull Einträge. Auf diese Weise müssen Sie nur prüfen, ob der entsprechende Schlüssel existiert.

Hinzufügen NSDictionary+NullReplacement

- (NSDictionary *)dictionaryByRemovingNulls{
    const NSMutableDictionary *replaced = [self mutableCopy];
    const id nul = [NSNull null];

    for (NSString *key in self) {
        id object = [self objectForKey:key];
        if (object == nul) [replaced removeObjectForKey:key];

        else if ([object isKindOfClass:[NSDictionary class]]) [replaced setObject:[object dictionaryByRemovingNulls] forKey:key];
        else if ([object isKindOfClass:[NSArray class]]) [replaced setObject:[object arrayByRemovingNulls] forKey:key];
    }
    return [NSDictionary dictionaryWithDictionary:[replaced copy]];
}

Und in NSArray+NullReplacement

- (NSArray *)arrayByRemovingNulls {
    NSMutableArray *replaced = [self mutableCopy];
    const id nul = [NSNull null];

    for (int idx = [replaced count]-1; idx >=0; idx--) {
        id object = [replaced objectAtIndex:idx];
        if (object == nul) [replaced removeObjectAtIndex:idx];
        else if ([object isKindOfClass:[NSDictionary class]]) [replaced replaceObjectAtIndex:idx withObject:[object dictionaryByRemovingNulls]];
        else if ([object isKindOfClass:[NSArray class]]) [replaced replaceObjectAtIndex:idx withObject:[object arrayByRemovingNulls]];
    }
    return [replaced copy];
}

3voto

justin Punkte 103032

Eine andere Variante:

NSDictionary * NewDictionaryReplacingNSNullWithEmptyNSString(NSDictionary * dict) {
    NSMutableDictionary * const m = [dict mutableCopy];    
    NSString * const empty = @"";
    id const nul = [NSNull null];
    NSArray * const keys = [m allKeys];
    for (NSUInteger idx = 0, count = [keys count]; idx < count; ++idx) {
        id const key = [keys objectAtIndex:idx];
        id const obj = [m objectForKey:key];
        if (nul == obj) {
            [m setObject:empty forKey:key]; 
        }
    }

    NSDictionary * result = [m copy];
    [m release];
    return result;
}

Das Ergebnis ist das gleiche wie erscheint ziemlich identisch mit dem von Jacob, aber die Geschwindigkeits- und Speicheranforderungen sind bei den von mir durchgeführten Tests um die Hälfte bis ein Drittel niedriger (ARC oder MRC). Natürlich können Sie es auch als Kategorie-Methode verwenden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X