【问题标题】:How to remove a null value from NSDictionary如何从 NSDictionary 中删除空值
【发布时间】:2012-12-18 08:44:34
【问题描述】:

我有一个 JSON 提要:

{
    "count1" = 2;
    "count2" = 2;
    idval = 40;
    level = "<null>";
    "logo_url" = "/assets/logos/default_logo_medium.png";
    name = "Golf Club";
    "role_in_club" = Admin;
}

问题是"&lt;null&gt;"。在将其保存到 NSUserDefaults 之前,我无法弄清楚如何将其从 NSDictionary 中删除。

【问题讨论】:

标签: ios objective-c swift dictionary nsdictionary


【解决方案1】:

遍历字典并查找任何空条目并将其删除。

NSMutableDictionary *prunedDictionary = [NSMutableDictionary dictionary];
for (NSString * key in [yourDictionary allKeys])
{
    if (![[yourDictionary objectForKey:key] isKindOfClass:[NSNull class]])
        [prunedDictionary setObject:[yourDictionary objectForKey:key] forKey:key];
}

之后,prunedDictionary 应该在原始字典中包含所有非空项。

【讨论】:

  • 我想知道哪个性能更好:创建字典的可变副本,然后从中删除对象或手动将所有值添加到字典中......
  • @RichardJ.RossIII 除非数组 非常 大,否则真的没关系。如果数组 足够大,我会尝试两种方式,看看哪个最快。
【解决方案2】:

要删除它,请将其转换为可变字典并删除键“级别”的对象;

NSDictionary* dict = ....;  // this is the dictionary to modify
NSMutableDictionary* mutableDict = [dict mutableCopy];
[mutableDict removeObjectForKey:@"level"];
dict = [mutableDict copy];

如果您不使用 ARC,则需要添加一些对“释放”的调用。

更新:

如果您不知道 "&lt;null&gt;" 对象的键名,那么您必须进行迭代:

NSDictionary* dict = ....;  // this is the dictionary to modify
NSMutableDictionary* mutableDict = [dict mutableCopy];
for (id key in dict) {
    id value = [dict objectForKey: key];
    if ([@"<null>" isEqual: value]) {
        [mutableDict removeObjectForKey:key];
    }
}
dict = [mutableDict copy];

为了定位"&lt;null&gt;" 值,我使用了字符串比较,因为"&lt;null&gt;" 是您示例中的字符串。但我不确定是否真的如此。

【讨论】:

  • 事实并非如此。如果它是一个不会有问题的字符串。这里的问题是解析将产生一个NSNull 实例读取“”并且该值不能存储在NSUserDefaults 中。
  • 我有点困惑。问题中的示例不是 JSON,但很可能是字典的 NSLog 输出(在解析 JSON 数据之后)。如果键 level 的值是 NSNull 实例,它会打印 &lt;null&gt; 而不是 "&lt;null&gt;"。所以要么值是字符串,要么样本错误。
  • 加布里埃拉你是对的。问题是它正在获取一个存储为“”的值并且它无法识别它。通常它会给我一个像 null 这样的值。
【解决方案3】:

另一种变体,没有(显式)循环:

NSMutableDictionary *dict = [yourDictionary mutableCopy];
NSArray *keysForNullValues = [dict allKeysForObject:[NSNull null]];
[dict removeObjectsForKeys:keysForNullValues];

【讨论】:

  • 同样,您可以通过将 [NSNull null] 替换为 @"" 来删除所有空条目
  • 这是一个很酷的代码,但是如果我们将字典放入数组中,我们可以做什么。
【解决方案4】:

使用它从字典中删除 null

- (NSMutableDictionary *)recursive:(NSMutableDictionary *)dictionary {
for (NSString *key in [dictionary allKeys]) {    
    id nullString = [dictionary objectForKey:key];   
    if ([nullString isKindOfClass:[NSDictionary class]]) {
        [self recursive:(NSMutableDictionary*)nullString];
    } else {
        if ((NSString*)nullString == (id)[NSNull null])
            [dictionary setValue:@"" forKey:key];
    }
}
return dictionary;
}

【讨论】:

  • 用@"" 替换空值,这可能是也可能不是你想要的:-)
  • “[字典 setValue:@"" forKey:key];”这可能会崩溃。子/递归字典可能不是 mutableDictionary。所以我们可以使用一个新的 mutableDictionary 来收集每个非空值和子字典值。
【解决方案5】:

我相信这是最节省资源的方式

// NSDictionary 上的类别实现

- (NSDictionary *)dictionaryByRemovingNullValues {

    NSMutableDictionary * d;
    for (NSString * key in self) {

        if (self[key] == [NSNull null]) {
            if (d == nil) {
                d = [NSMutableDictionary dictionaryWithDictionary:self];
            }
            [d removeObjectForKey:key];
        }

    }

    if (d == nil) {
        return self;
    }

    return d;
}

【讨论】:

    【解决方案6】:

    我已经为 NSJSOn 序列化类创建了一个类别。

    创建一个类别并导入类以使用其方法...

    // Mutable containers are required to remove nulls.
    if (replacingNulls)
    {
        // Force add NSJSONReadingMutableContainers since the null removal depends on it.
        opt = opt || NSJSONReadingMutableContainers;
    }
    
    id JSONObject = [self JSONObjectWithData:data options:opt error:error];
    
    if ((error && *error) || !replacingNulls)
    {
        return JSONObject;
    }
    
    [JSONObject recursivelyReplaceNullsIgnoringArrays:ignoreArrays withString:replaceString];
    return JSONObject;
    

    【讨论】:

      【解决方案7】:

      这是我的基于类别的递归解决方案,用于包含字典和数组的字典,其中值也可以是字典和数组:

      文件NSDictionary+Dario.m

      #import "NSArray+Dario.h"
      
      @implementation NSDictionary (Dario)
      
      - (NSDictionary *) dictionaryByReplacingNullsWithEmptyStrings {
      
          const NSMutableDictionary *replaced = [NSMutableDictionary new];
          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:[object dictionaryByReplacingNullsWithEmptyStrings] forKey:key];
              } else if ([object isKindOfClass:[NSArray class]]) {
                  [replaced setObject:[object arrayByReplacingNullsWithEmptyStrings] forKey:key];
              } else {
                  [replaced setObject:object forKey:key];
              }
          }
          return [NSDictionary dictionaryWithDictionary:(NSDictionary*)replaced];
      }
      
      @end
      

      文件NSArray+Dario.m

      #import "NSDictionary+Dario.h"
      
      @implementation NSArray (Dario)
      
      - (NSArray *) arrayByReplacingNullsWithEmptyStrings {
          const NSMutableArray *replaced = [NSMutableArray new];
          const id nul = [NSNull null];
          const NSString *blank = @"";
      
          for (int i=0; i<[self count]; i++) {
              const id object = [self objectAtIndex:i];
      
              if ([object isKindOfClass:[NSDictionary class]]) {
                  [replaced setObject:[object dictionaryByReplacingNullsWithEmptyStrings] atIndexedSubscript:i];
              } else if ([object isKindOfClass:[NSArray class]]) {
                  [replaced setObject:[object arrayByReplacingNullsWithEmptyStrings] atIndexedSubscript:i];
              } else if (object == nul){
                  [replaced setObject:blank atIndexedSubscript:i];
              } else {
                  [replaced setObject:object atIndexedSubscript:i];
              }
          }
          return [NSArray arrayWithArray:(NSArray*)replaced];
      }
      

      【讨论】:

        【解决方案8】:

        我尝试了你的问题的解决方案,我明白了

        NSDictionary *dict = [[NSDictionary alloc]initWithObjectsAndKeys:@"2",@"count1",@"2",@"count2",@"40",@"idval",@"<null>",@"level",@"/assets/logos/default_logo_medium.png",@"logo_url",@"Golf Club",@"name",@"role_in_club",@"Admin", nil];
        NSMutableDictionary *mutableDict = [dict mutableCopy];
        for (NSString *key in [dict allKeys]) {
            if ([dict[key] isEqual:[NSNull null]]) {
                mutableDict[key] = @""; 
            }
            if([dict[key] isEqualToString:@"<null>"])
            {
                mutableDict[key] = @"";
            }
        }
        dict = [mutableDict copy];
        NSLog(@"The dict is - %@",dict);
        

        最终答案是

        The dict is - {
        Admin = "role_in_club";
        count1 = 2;
        count2 = 2;
        idval = 40;
        level = "";
        "logo_url" = "/assets/logos/default_logo_medium.png";
        name = "Golf Club";
        }
        

        【讨论】:

        • 我试过了,然后我才用结果发布了我的答案。它有效。
        【解决方案9】:

        我就是这样做的。

        NSMutableDictionary *prunedDict = [NSMutableDictionary dictionary];
        [self enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
          if (![obj isKindOfClass:[NSNull class]]) {
            prunedDict[key] = obj;
          }
        }];
        

        【讨论】:

          【解决方案10】:

          以下代码在结果为数组或字典的情况下是可以的,你可以通过编辑代码将返回的结果更改为nil或空字符串

          函数是递归的,所以可以解析字典中的数组。

          -(id)changeNull:(id)sender{
              
              id newObj;
              
              if ([sender isKindOfClass:[NSArray class]]){
          
                  NSMutableArray *newArray = [[NSMutableArray alloc] init];
                  
                  
                  for (id item in sender){
                  
                      [newArray addObject:[self changeNull:item]];
                  
                  }
                  
                  newObj = newArray;
              }
              
              else if ([sender isKindOfClass:[NSDictionary class]]){
                  
                  NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init];
                  
                  for (NSString *key in sender){
                      
                      NSDictionary *oldDict = (NSDictionary*)sender;
                      
                      
                      id item = oldDict[key];
          
                      if (![item isKindOfClass:[NSDictionary class]] && ![item isKindOfClass:[NSArray class]]){
          
                          if ([item isEqual:[NSNull null]]){
                              item = @"";
                              
                          }
                          
                          [newDict setValue:item forKey:key];
          
                      }
                      else{
                          
                          [newDict setValue:[self changeNull:item] forKey:key];
                          
                      }
                  }
                  newObj = newDict;
              }
              
              return newObj;
          }
          

          导致:

          jsonresult (
              {
                  Description = "<null>";
                  Id = 1;
                  Name = High;
              },
                  {
                  Description = "<null>";
                  Id = 2;
                  Name = Medium;
              },
                  {
                  Description = "<null>";
                  Id = 3;
                  Name = Low;
              }
          )
          
          change null (
              {
                  Description = "";
                  Id = 1;
                  Name = High;
              },
                  {
                  Description = "";
                  Id = 2;
                  Name = Medium;
              },
                  {
                  Description = "";
                  Id = 3;
                  Name = Low;
              }
          )
          

          【讨论】:

            【解决方案11】:

            Swift 3.0/4.0解决方案

            以下是解决方案,当JSON 拥有sub-dictionaries。这将遍历所有dictionariesJSON 的子-dictionaries 并从JSON 中删除NULL(NSNull) key-value 对。

            extension Dictionary {
            
                func removeNull() -> Dictionary {
                    let mainDict = NSMutableDictionary.init(dictionary: self)
                    for _dict in mainDict {
                        if _dict.value is NSNull {
                            mainDict.removeObject(forKey: _dict.key)
                        }
                        if _dict.value is NSDictionary {
                            let test1 = (_dict.value as! NSDictionary).filter({ $0.value is NSNull }).map({ $0 })
                            let mutableDict = NSMutableDictionary.init(dictionary: _dict.value as! NSDictionary)
                            for test in test1 {
                                mutableDict.removeObject(forKey: test.key)
                            }
                            mainDict.removeObject(forKey: _dict.key)
                            mainDict.setValue(mutableDict, forKey: _dict.key as? String ?? "")
                        }
                        if _dict.value is NSArray {
                            let mutableArray = NSMutableArray.init(object: _dict.value)
                            for (index,element) in mutableArray.enumerated() where element is NSDictionary {
                                let test1 = (element as! NSDictionary).filter({ $0.value is NSNull }).map({ $0 })
                                let mutableDict = NSMutableDictionary.init(dictionary: element as! NSDictionary)
                                for test in test1 {
                                    mutableDict.removeObject(forKey: test.key)
                                }
                                mutableArray.replaceObject(at: index, with: mutableDict)
                            }
                            mainDict.removeObject(forKey: _dict.key)
                            mainDict.setValue(mutableArray, forKey: _dict.key as? String ?? "")
                        }
                    }
                    return mainDict as! Dictionary<Key, Value>
                }
             }
            

            【讨论】:

            • 谢谢,我已经更新了我的答案。实际上嵌入链接的答案也是我发布的。
            【解决方案12】:

            在你的视图控制器中添加这3个方法,并像这样调用这个方法

            NSDictionary *dictSLoginData = [self removeNull:[result valueForKey:@"data"]];
            
            - (NSDictionary*)removeNull:(NSDictionary *)dict {
            
                NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary: dict];
            
                const id nul = [NSNull null];
                const NSString *blank = @"";
            
                for (NSString *key in [dict allKeys]) {
            
                    const id object = [dict objectForKey: key];
                    if (object == nul) {
                        [replaced setObject: blank forKey: key];
                    } else if([object isKindOfClass: [NSDictionary class]]) {
                        [replaced setObject: [self replaceNull:object] forKey: key];
                    } else if([object isKindOfClass: [NSArray class]]) {
                        [replaced setObject: [self replaceNullArray:object] forKey: key];
                    }
                }
                return [NSDictionary dictionaryWithDictionary: replaced];
            }
            
            - (NSArray *)replaceNullArray:(NSArray *)array {
            
                const id nul = [NSNull null];
                const NSString *blank = @"";
            
                NSMutableArray *replaced = [NSMutableArray arrayWithArray:array];
            
                for (int i=0; i < [array count]; i++) {
                    const id object = [array objectAtIndex:i];
                    if (object == nul) {
                        [replaced replaceObjectAtIndex:i withObject:blank];
                    } else if([object isKindOfClass: [NSDictionary class]]) {
                        [replaced replaceObjectAtIndex:i withObject:[self replaceNull:object]];
                    } else if([object isKindOfClass: [NSArray class]]) {
                        [replaced replaceObjectAtIndex:i withObject:[self replaceNullArray:object]];
                    }
                }
                return replaced;
            }
            
            - (NSDictionary *)replaceNull:(NSDictionary *)dict {
            
                const id nul = [NSNull null];
                const NSString *blank = @"";
            
                NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary: dict];
            
                for (NSString *key in [dict allKeys]) {
                    const id object = [dict objectForKey: key];
                    if (object == nul) {
                        [replaced setObject: blank forKey: key];
                    } else if ([object isKindOfClass: [NSDictionary class]]) {
                        [replaced setObject: [self replaceNull:object] forKey: key];
                    } else if([object isKindOfClass: [NSArray class]]) {
                        [replaced setObject: [self replaceNullArray:object] forKey: key];
                    }
                }
                return replaced;
            }
            

            【讨论】:

              【解决方案13】:

              修改@sinh99 答案。使用新的 NSMutableDictionary 来收集非空值和子字典值。

              
              - (NSMutableDictionary *)recursiveRemoveNullValues:(NSDictionary *)dictionary {
              
                  NSMutableDictionary *mDictionary = [NSMutableDictionary new];
                  for (NSString *key in [dictionary allKeys]) {
                      id nullString = [dictionary objectForKey:key];
              
                      if ([nullString isKindOfClass:[NSDictionary class]]) {
                          NSMutableDictionary *mDictionary_sub = [self recursiveRemoveNullValues:(NSDictionary*)nullString];
                          [mDictionary setObject:mDictionary_sub forKey:key];
                      } else {
              
                          if ((NSString*)nullString == (id)[NSNull null]) {
                              [mDictionary setValue:@"" forKey:key];
                          } else {
                              [mDictionary setValue:nullString forKey:key];
                          }
                      }
                  }
              
                  return mDictionary;
              }
              
              
              

              【讨论】:

                【解决方案14】:

                Swift - 支持嵌套 NSNull

                首先,我们在 Swift 中使用Dictionary 而不是NSDictionary

                要删除任何嵌套级别(包括数组字典)中的任何 NSNull外观,请尝试以下操作:

                extension Dictionary where Key == String {
                    func removeNullsFromDictionary() -> Self {
                        var destination = Self()
                        for key in self.keys {
                            guard !(self[key] is NSNull) else { destination[key] = nil; continue }
                            guard !(self[key] is Self) else { destination[key] = (self[key] as! Self).removeNullsFromDictionary() as? Value; continue }
                            guard self[key] is [Value] else { destination[key] = self[key]; continue }
                
                            let orgArray = self[key] as! [Value]
                            var destArray: [Value] = []
                            for item in orgArray {
                                guard let this = item as? Self else { destArray.append(item); continue }
                                destArray.append(this.removeNullsFromDictionary() as! Value)
                            }
                            destination[key] = destArray as? Value
                        }
                        return destination
                    }
                }
                

                注意字典的key应该是String

                【讨论】:

                  猜你喜欢
                  • 2016-07-06
                  • 2018-09-23
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-06-25
                  • 1970-01-01
                  • 2015-01-18
                  • 2019-09-05
                  相关资源
                  最近更新 更多