Reputation: 37053
I have a dictionary containing UIColor
objects hashed by an enum value, ColorScheme
:
var colorsForColorScheme: [ColorScheme : UIColor] = ...
I would like to be able to extract an array of all the colors (the values) contained by this dictionary. I thought I could use the values
property, as is used when iterating over dictionary values (for value in dictionary.values {...}
), but this returns an error:
let colors: [UIColor] = colorsForColorSchemes.values
~~~~~~~~~~~~~~~~~~~~~^~~~~~~
'LazyBidrectionalCollection<MapCollectionView<Dictionary<ColorScheme, UIColor>, UIColor>>' is not convertible to 'UIColor'
It seems that rather than returning an Array
of values, the values
method returns a more abstract collection type. Is there a way to get an Array
containing the dictionary's values without extracting them in a for-in
loop?
Upvotes: 208
Views: 141495
Reputation: 1061
You can also use flatMap
:
let colors = colorsForColorScheme.values.flatMap { $0 }
Upvotes: 2
Reputation: 6893
Firstly, from the following statement, it seems that your variable(dictionary) name is colorsForColorScheme
var colorsForColorScheme: [ColorScheme : UIColor] = ...
while you are trying to get the values from colorsForColorSchemes
dictionary when you did-
let colors: [UIColor] = colorsForColorSchemes.values
which should give you a compile time error. Anyways I am assuming that you had a typo, and you dictionary's name is colorsForColorSchemes
. So, here is the solution-
As mentioned earlier, because of the type inference property in swift, your code can infer that the returned type from the .values
function is returning an array of UIColor. However, Swift wants to be type-safe, so when you store the values in the colors
array, you need to explicitly define that. For swift 5 and above, now you could just do following-
let colors = [UIColor](colorsForColorSchemes.values)
Upvotes: 7
Reputation: 1656
You can map dictionary to an array of values:
let colors = colorsForColorScheme.map { $0.1 }
Closure takes a key-value tuple from dictionary and returns just a value. So, map function produces an array of values.
More readable version of the same code:
let colors = colorsForColorScheme.map { (scheme, color) in
return color
}
UPDATE
From Xcode 9.0, dictionary values can be accessed using values
property, which conforms to Collection
protocol:
let colors = colorsForColorScheme.values
Typically you just want it as an array:
let colors = Array(dict.values)
and that's it.
Upvotes: 92
Reputation: 1143
I've found this to be the most useful in Swift 5:
colorsForColorSchemes.allValues
See docs - https://developer.apple.com/documentation/foundation/nsdictionary/1408915-allvalues
Upvotes: 0
Reputation: 4778
you can create an extension on LazyMapCollection
public extension LazyMapCollection {
func toArray() -> [Element]{
return Array(self)
}
}
colorsForColorSchemes.values.toArray()
or colorsForColorSchemes.keys.toArray()
Upvotes: 10
Reputation: 37053
As of Swift 2.0, Dictionary
’s values
property now returns a LazyMapCollection
instead of a LazyBidirectionalCollection
. The Array
type knows how to initialise itself using this abstract collection type:
let colors = Array(colorsForColorSchemes.values)
Swift's type inference already knows that these values are UIColor
objects, so no type casting is required, which is nice!
Upvotes: 354