Diccionario Swift: obtenga valores como matriz

150

Tengo un diccionario que contiene UIColorobjetos hash con un valor de enumeración ColorScheme:

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

Me gustaría poder extraer una matriz de todos los colores (los valores) contenidos en este diccionario. Pensé que podría usar la valuespropiedad, como se usa al iterar sobre los valores del diccionario ( for value in dictionary.values {...}), pero esto devuelve un error:

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

Parece que, en lugar de devolver un Arrayvalor, el valuesmétodo devuelve un tipo de colección más abstracto. ¿Hay alguna manera de obtener un que Arraycontenga los valores del diccionario sin extraerlos en un for-inbucle?

Stuart
fuente
1
Swift 5: colorsForColorSchemes.values
Juan Boero

Respuestas:

284

A partir de Swift 2.0, Dictionaryla valuespropiedad ahora devuelve un en LazyMapCollectionlugar de un LazyBidirectionalCollection. El Arraytipo sabe cómo inicializarse utilizando este tipo de colección abstracta:

let colors = Array(colorsForColorSchemes.values)

La inferencia de tipos de Swift ya sabe que estos valores son UIColorobjetos, por lo que no se requiere conversión de tipos, ¡lo cual es bueno!

Stuart
fuente
1
También puede convertirlo como una matriz con objetos escritos. ¡Funciona genial! gracias dejar colores = [CustomColorObject] (colorsForColorSchemes.values)
bolnad
66
Parece que en Swift 2.0, Dictionary.values ​​ahora devuelve una LazyMapCollection en lugar de una LazyBidirectionalCollection. Desafortunadamente, .array no está definido en una colección LazyMapCollection. Sin embargo, la forma Array (dictionary.values) todavía funciona bien, ya que los tipos de matriz saben cómo inicializarse a partir de una Colección LazyMap.
Tod Cunningham
8
Tenga en cuenta que el orden de los valores puede ser inesperado. Por ejemplo [0: "small", 1: "medium", 2: "large"], probablemente NO generará["small", "medium", "large"]
Simon Bengtsson
55

Puede asignar el diccionario a una matriz de valores:

let colors = colorsForColorScheme.map { $0.1 }

El cierre toma una tupla clave-valor del diccionario y devuelve solo un valor. Entonces, la función de mapa produce una matriz de valores.

Versión más legible del mismo código:

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

ACTUALIZAR

Desde Xcode 9.0, se puede acceder a los valores del diccionario utilizando la valuespropiedad, que se ajusta al Collectionprotocolo:

let colors = colorsForColorScheme.values

Por lo general, solo lo quieres como una matriz:

let colors = Array(dict.values)

y eso es.

pjuzeliunas
fuente
2
Pero en realidad esta es una forma legible de obtener una matriz de colores let = Array (colorsForColorScheme.values)
Renetik
1
Me encanta esta solución
Navy Seal
@pjuzeliunas ya que esta es la mejor respuesta aquí, acabo de editar la última para 2020. Obviamente, relájate, edita, etc. saludos y gracias!
Fattie
10

Utilizar colorsForColorScheme.map({$0.value})

Vishal kundaliya
fuente
8

puedes crear una extensión en LazyMapCollection

public extension LazyMapCollection  {

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

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

GSerjo
fuente
3

En primer lugar, de la siguiente declaración, parece que el nombre de su variable (diccionario) es colorsForColorScheme

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

mientras intentas obtener los valores del colorsForColorSchemesdiccionario cuando lo hiciste-

let colors: [UIColor] = colorsForColorSchemes.values

que debería darte un error de tiempo de compilación. De todos modos, supongo que tenías un error tipográfico y el nombre de tu diccionario es colorsForColorSchemes. Entonces, aquí está la solución.

Como se mencionó anteriormente, debido a la propiedad de inferencia de tipo en swift, su código puede inferir que el tipo devuelto por la .valuesfunción está devolviendo una matriz de UIColor. Sin embargo, Swift quiere ser seguro para los tipos, por lo que cuando almacena los valores en la colorsmatriz, debe definirlo explícitamente. Para Swift 5 y superior, ahora podría hacer lo siguiente:

let colors = [UIColor](colorsForColorSchemes.values)
Natasha
fuente