【问题标题】:Determining if Swift dictionary contains key and obtaining any of its values确定 Swift 字典是否包含键并获取其任何值
【发布时间】:2015-03-23 15:25:53
【问题描述】:

我目前正在使用以下(笨拙的)代码来确定(非空)Swift 字典是否包含给定的键并从同一字典中获取一个(任意)值。

如何在 Swift 中更优雅地表达这一点?

// excerpt from method that determines if dict contains key
if let _ = dict[key] {
    return true
}
else {
    return false
}

// excerpt from method that obtains first value from dict
for (_, value) in dict {
    return value
}

【问题讨论】:

  • 如果你觉得indexForKey更清晰更明确,可以使用; stackoverflow.com/a/29299943/294884
  • 很多时候你想要的基本上是:cityName:String = dict["city"] ?? "" ?? "" 这里的意思基本上是“如果没有这样的键,返回一个空白”。

标签: swift dictionary


【解决方案1】:

您不需要任何 特殊代码来执行此操作,因为这是字典已经完成的工作。当您获取 dict[key] 时,您知道字典是否包含键,因为您返回的 Optional 不是 nil(并且它包含值)。

所以,如果您只是想回答字典是否包含键的问题,请询问:

let keyExists = dict[key] != nil

如果您想要该值并且您知道字典包含键,请说:

let val = dict[key]!

但是,如果像通常发生的那样,您不知道它包含密钥 - 您想获取并使用它,但前提是它存在 - 然后使用类似 if let 的东西:

if let val = dict[key] {
    // now val is not nil and the Optional has been unwrapped, so use it
}

【讨论】:

  • 我不关注。我刚刚获得了一个值(两次)。你还想要什么?
  • 没有“第一个值”这样的东西;字典是无序的。如果您只想要没有键的值,请说dict.values
  • 小心,因为dict.values 是不透明的。你可以循环通过它,但仅此而已。 (好吧,这还不是全部,但请幽默。)如果您想将其具体化为一个数组,请使用dict.values.array
  • @bubakazouba 试试这个:let d = ["hey":"ho"]; let s = d["hey"]; print(s) 这是一个可选的,就像它一直以来一样。
  • @Kross 这是一个非常深刻的问题,因此请单独提出。
【解决方案2】:

为什么不简单地检查dict.keys.contains(key)? 在值为 nil 的情况下,检查 dict[key] != nil 将不起作用。 例如字典[String: String?]

【讨论】:

  • 或者在这种情况下,您可以使用if let val = dict[key] as? String,而不是只写if let val = dict[key]
  • 这可能非常浪费,因为 (1) 您调用 dict.keys 创建一个包含所有键的数组,然后 (2) 按顺序检查每个键,直到找到一个(或没有!) .我意识到您正在尝试解决 [String: String?] 的情况,但会非常小心地使用该解决方案...
  • 正如@charles 提到的,这将消除使用字典提供的快速查找优势,所以我建议不要这样做,但仍然绝对是一个有效的选择。
  • 你应该永远不要使用这种方法,因为直接字典访问的复杂度为 O(n) 而不是理论上的(取决于散列函数的实现) O(1)。跨度>
  • @charles 我在keys 的文档中没有看到它说它创建了一个数组或者contains 是O(n)。它说这是一个视图,但似乎没有表明它的性能特征。希望它不会复制并且是 O(1)。
【解决方案3】:

如果 Dictionary 包含键但值为 nil,则接受的答案 let keyExists = dict[key] != nil 将不起作用。

如果您想确保 Dictionary 根本不包含密钥,请使用它(在 Swift 4 中测试)。

if dict.keys.contains(key) {
  // contains key
} else { 
  // does not contain key
}

【讨论】:

  • 这和韩的回答一样。
  • 检查== nil 确实有效,即使字典有可选值。这是因为查找结果被包装为Optional。另一方面,要检查查找的值是否真的是nil 而不是不存在,您可以使用== .some(nil)
  • 与其他方法的 O(1) 查找相比,我会增加使用此方法的效率。我相信这是 O(n) 查找
  • @AlbertoVega-MSFT 这是O(1)。另请参阅:github.com/apple/swift-evolution/blob/master/proposals/… 是什么让您认为是O(n)
  • Dictionary.Keys.contains(...) 函数 here 的文档说它具有 O(n) 复杂性,其中 n 是序列的长度。
【解决方案4】:

看起来你从 @matt 得到了你需要的东西,但是如果你想要一种快速的方法来获取一个键的值,或者如果该键不存在则只获取第一个值:

extension Dictionary {
    func keyedOrFirstValue(key: Key) -> Value? {
        // if key not found, replace the nil with 
        // the first element of the values collection
        return self[key] ?? first(self.values)
        // note, this is still an optional (because the
        // dictionary could be empty)
    }
}

let d = ["one":"red", "two":"blue"]

d.keyedOrFirstValue("one")  // {Some "red"}
d.keyedOrFirstValue("two")  // {Some "blue"}
d.keyedOrFirstValue("three")  // {Some "red”}

请注意,不能保证您实际上会得到什么作为第一个值,它只是在这种情况下返回“red”。

【讨论】:

  • ?? 运算符的良好使用从我那里得到了我方便的解决方案,但作为默认值的扩展,可能会出现数据不安全或意外行为。这听起来像是Dictionary 的具体子类应该使用的东西。如果nil 返回不包括特定情况的功能,您多久需要一次第一个值?
【解决方案5】:

我对存储可选 NSAttributedString 的缓存实现的解决方案:

public static var attributedMessageTextCache    = [String: NSAttributedString?]()

    if attributedMessageTextCache.index(forKey: "key") != nil
    {
        if let attributedMessageText = TextChatCache.attributedMessageTextCache["key"]
        {
            return attributedMessageText
        }
        return nil
    }

    TextChatCache.attributedMessageTextCache["key"] = .some(.none)
    return nil

【讨论】:

    【解决方案6】:
    if dictionayTemp["quantity"] != nil
        {
    
      //write your code
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      • 2013-07-02
      • 1970-01-01
      • 2019-05-13
      • 2017-02-17
      相关资源
      最近更新 更多