此问题类似于this question,但此方法仅适用于字典的根级别。
我希望用空字符串替换任何出现的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提要中提取的,因此我收到的数据是动态的(我不希望每次更改Feed时都必须更新应用程序)。
答案 0 :(得分: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" = "";
};
答案 1 :(得分:11)
它对我有用,我使用嵌套循环在整个字典中用nil替换所有NULL,包括NSArray。
- (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];
}
答案 2 :(得分: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
}
答案 3 :(得分:2)
以下方法适用于任意数量的嵌套arrray字典:
- (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];
}
答案 4 :(得分:0)
此代码
@interface NSDictionary (JRAdditions)
- (NSDictionary *) dictionaryByReplacingNullsWithStrings;
@end
Monkey patches NSDictionary - 这意味着你可以调用dictionaryByReplacing ... 不仅仅是根,而是任何嵌套的词典。
从设计的角度来看,我并不是真的同意这一点,但它确实解决了你的问题。
答案 5 :(得分: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];
}
答案 6 :(得分: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;
}
答案 7 :(得分: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;
}