【问题标题】:Swift Dictionary: Get values as arraySwift Dictionary:将值作为数组获取
【发布时间】:2015-01-15 06:41:00
【问题描述】:

我有一本字典,其中包含由枚举值 ColorScheme 散列的 UIColor 对象:

var colorsForColorScheme: [ColorScheme : UIColor] = ...

我希望能够提取此字典包含的所有颜色(值)的数组。我想我可以使用 values 属性,就像在遍历字典值 (for value in dictionary.values {...}) 时使用的那样,但这会返回一个错误:

let colors: [UIColor] = colorsForColorSchemes.values
                        ~~~~~~~~~~~~~~~~~~~~~^~~~~~~
'LazyBidrectionalCollection<MapCollectionView<Dictionary<ColorScheme, UIColor>, UIColor>>' is not convertible to 'UIColor'

似乎values 方法不是返回值的Array,而是返回更抽象的集合类型。有没有办法获得包含字典值的Array 而无需在for-in 循环中提取它们?

【问题讨论】:

  • Swift 5: colorsForColorSchemes.values

标签: arrays dictionary swift


【解决方案1】:

从 Swift 2.0 开始,Dictionaryvalues 属性现在返回 LazyMapCollection 而不是 LazyBidirectionalCollectionArray 类型知道如何使用这个抽象集合类型来初始化自己:

let colors = Array(colorsForColorSchemes.values)

Swift 的类型推断已经知道这些值是UIColor 对象,所以不需要类型转换,这很好!

【讨论】:

  • 您也可以将其转换为带有类型对象的数组。效果很好!谢谢 let colors = [CustomColorObject](colorsForColorSchemes.values)
  • 看起来在 Swift 2.0 中,Dictionary.values 现在返回一个 LazyMapCollection 而不是 LazyBidirectionalCollection。不幸的是,.array 没有在 LazyMapCollection 上定义。但是,Array(dictionary.values) 方式仍然可以正常工作,因为数组类型知道如何从 LazyMapCollection 初始化自身。
  • 请注意,值的顺序可能出乎意料。例如[0: "small", 1: "medium", 2: "large"] 可能不会 生成["small", "medium", "large"]
  • @SimonBengtsson 虽然这通常是个好建议,但 swift 文档确实表明 values 将按密钥对顺序排列,至少从 Swift 4 开始。“当迭代时,值出现在这个集合中与它们在字典的键值对中出现的顺序相同。” developer.apple.com/documentation/swift/dictionary/…
  • 意外的部分是密钥对顺序与代码中定义的顺序不同,如您链接的文档中的示例所示。迭代和打印提到的字典 ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"] Japan 的值时,尽管是最后定义的,但仍打印在中间。
【解决方案2】:

您可以将字典映射到值数组:

let colors = colorsForColorScheme.map { $0.1 }

闭包从字典中获取一个键值元组并只返回一个值。因此,map 函数会生成一个值数组。

相同代码的可读性更高的版本:

let colors = colorsForColorScheme.map { (scheme, color) in
    return color
}

更新

从 Xcode 9.0 开始,可以使用 values 属性访问字典值,该属性符合 Collection 协议:

let colors = colorsForColorScheme.values

通常你只希望它作为一个数组:

let colors = Array(dict.values)

就是这样。

【讨论】:

  • 但实际上这是获取数组的可读方式 let colors = Array(colorsForColorScheme.values)
  • 喜欢这个解决方案
  • @pjuzeliunas 因为这是这里的最佳答案,我刚刚编辑了 2020 年的最新版本。显然放松、编辑等!欢呼,谢谢!
【解决方案3】:

使用colorsForColorScheme.map({$0.value})

【讨论】:

    【解决方案4】:

    你可以在LazyMapCollection上创建一个扩展

    public extension LazyMapCollection  {
    
        func toArray() -> [Element]{
            return Array(self)
        }
    }
    

    colorsForColorSchemes.values.toArray()colorsForColorSchemes.keys.toArray()

    【讨论】:

      【解决方案5】:

      首先,从以下语句来看,您的变量(字典)名称似乎是colorsForColorScheme

      var colorsForColorScheme: [ColorScheme : UIColor] = ... 
      

      当您尝试从colorsForColorSchemes 字典中获取值时-

      let colors: [UIColor] = colorsForColorSchemes.values
      

      这应该会给你一个编译时错误。无论如何,我假设您有错字,而您的字典名称是colorsForColorSchemes。所以,这里是解决方案-

      如前所述,由于 swift 中的类型推断属性,您的代码可以推断出 .values 函数返回的类型正在返回 UIColor 数组。但是,Swift 希望是类型安全的,因此当您将值存储在 colors 数组中时,您需要明确定义它。对于 swift 5 及更高版本,现在您可以执行以下操作-

      let colors = [UIColor](colorsForColorSchemes.values)
      

      【讨论】:

      • 这是一个非常有趣的解决方案,而且资源不多。你有参考吗?谢谢。
      【解决方案6】:

      你也可以使用flatMap:

      let colors = colorsForColorScheme.values.flatMap { $0 }

      【讨论】:

        【解决方案7】:

        我发现这是 Swift 5 中最有用的:

        colorsForColorSchemes.allValues

        请参阅文档 - https://developer.apple.com/documentation/foundation/nsdictionary/1408915-allvalues

        【讨论】:

        • 这仅适用于 NS 字典。这只是 d.values 。在实践中Array(d.values)
        猜你喜欢
        • 2020-03-07
        • 2014-12-18
        • 2014-01-31
        • 1970-01-01
        • 1970-01-01
        • 2010-10-08
        • 2021-07-29
        • 2016-08-26
        • 1970-01-01
        相关资源
        最近更新 更多