Swift:如何从Dictionary中删除空值?

Anv*_*zov 17 null json nsdictionary ios swift

我是Swift的新手,我在从JSON文件中过滤NULL值并将其设置为Dictionary时遇到问题.我从服务器获取空值的JSON响应,它崩溃了我的应用程序.

这是JSON响应:

"FirstName": "Anvar",
"LastName": "Azizov",
"Website": null,
"About": null,
Run Code Online (Sandbox Code Playgroud)

我将非常感谢您的帮助来处理它.

UPD1:此时我决定以下一个方式做到这一点:

if let jsonResult = responseObject as? [String: AnyObject] {                    
    var jsonCleanDictionary = [String: AnyObject]()

    for (key, value) in enumerate(jsonResult) {
      if !(value.1 is NSNull) {
         jsonCleanDictionary[value.0] = value.1
      }
    }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*rný 23

斯威夫特4

我会通过合并做compactMapValuescompactMapValues:

dictionary.compactMapValues { $0 }
Run Code Online (Sandbox Code Playgroud)

字典示例

let json = [
    "FirstName": "Anvar",
    "LastName": "Azizov",
    "Website": nil,
    "About": nil,
]

let result = json.compactMapValues { $0 }
print(result) // ["FirstName": "Anvar", "LastName": "Azizov"]
Run Code Online (Sandbox Code Playgroud)

示例包括JSON解析

let jsonText = """
  {
    "FirstName": "Anvar",
    "LastName": "Azizov",
    "Website": null,
    "About": null
  }
  """

let data = jsonText.data(using: .utf8)!
let json = try? JSONSerialization.jsonObject(with: data, options: [])
if let json = json as? [String: Any?] {
    let result = json.compactMapValues { $0 }
    print(result) // ["FirstName": "Anvar", "LastName": "Azizov"]
}
Run Code Online (Sandbox Code Playgroud)


Ant*_*nio 11

您可以创建一个包含相应值为nil的键的数组:

let keysToRemove = dict.keys.array.filter { dict[$0]! == nil }
Run Code Online (Sandbox Code Playgroud)

然后循环遍历该数组的所有元素并从字典中删除键:

for key in keysToRemove {
    dict.removeValueForKey(key)
}
Run Code Online (Sandbox Code Playgroud)

更新2017.01.17

正如评论中所解释的那样,力展开算子虽然安全,但有点难看.可能有其他几种方法可以实现相同的结果,同一方法的更好看方式是:

let keysToRemove = dict.keys.filter {
  guard let value = dict[$0] else { return false }
  return value == nil
}
Run Code Online (Sandbox Code Playgroud)

  • @Hogdotmac 现在这绝对不是一种优雅的方式,但考虑到 `dict[$0]` 是一个可选的,它可能包含另一个可选的。force unwrap 是安全的,因为我们循环遍历键数组,所以每个键都存在 (3认同)
  • 力展开是这里的重量.这只是没有崩溃,因为值类型不是可选的.还有:永远不要强行打开包装 (2认同)

Dan*_* T. 6

我在Swift 2中得到了这个结论:

extension Dictionary where Value: AnyObject {

    var nullsRemoved: [Key: Value] {
        let tup = filter { !($0.1 is NSNull) }
        return tup.reduce([Key: Value]()) { (var r, e) in r[e.0] = e.1; return r }
    }
}
Run Code Online (Sandbox Code Playgroud)

对于Swift 3,答案相同:

extension Dictionary {

    /// An immutable version of update. Returns a new dictionary containing self's values and the key/value passed in.
    func updatedValue(_ value: Value, forKey key: Key) -> Dictionary<Key, Value> {
        var result = self
        result[key] = value
        return result
    }

    var nullsRemoved: [Key: Value] {
        let tup = filter { !($0.1 is NSNull) }
        return tup.reduce([Key: Value]()) { $0.0.updatedValue($0.1.value, forKey: $0.1.key) }
    }
}
Run Code Online (Sandbox Code Playgroud)

Swift 4中,事情变得容易多了.只需filter直接使用Dictionary's .

jsonResult.filter { !($0.1 is NSNull) }
Run Code Online (Sandbox Code Playgroud)

或者,如果您不想删除相关密钥,则可以执行以下操作:

jsonResult.mapValues { $0 is NSNull ? nil : $0 }
Run Code Online (Sandbox Code Playgroud)

这将替换NSNullnil而不是删除键.