Swift Dictionary:将值作为数组获取

Posted

技术标签:

【中文标题】Swift Dictionary:将值作为数组获取【英文标题】:Swift Dictionary: Get values as array 【发布时间】: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 【参考方案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)

以上是关于Swift Dictionary:将值作为数组获取的主要内容,如果未能解决你的问题,请参考以下文章

Swift4.2~数组和字典(Array, Dictionary)基本类型转换

如何制作一个包含特定值的Swift词典?

Swift4 JSONDecoder 期望解码 Dictionary<String, Any> 但找到了一个数组 [重复]

将值附加到数据数组并保存在 Userdefault swift

SWIFT“应解码 Dictionary<String, Any>,但找到了一个数组。”,underlyingError: nil))

无法在 Swift 中解析 JSON。 “应解码 Dictionary<String, Any>,但找到了一个数组。” [复制]