Dictionnaire rapide: obtenir des valeurs sous forme de tableau

151

J'ai un contenant dictionnaire UIColorobjets hachurées par une valeur ENUM, ColorScheme:

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

Je voudrais pouvoir extraire un tableau de toutes les couleurs (les valeurs) contenues dans ce dictionnaire. Je pensais pouvoir utiliser la valuespropriété, telle qu'elle est utilisée lors de l'itération sur les valeurs du dictionnaire ( for value in dictionary.values {...}), mais cela renvoie une erreur:

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

Il semble qu'au lieu de renvoyer une Arrayvaleur de valeurs, la valuesméthode renvoie un type de collection plus abstrait. Existe-t-il un moyen d'obtenir un Arraycontenant les valeurs du dictionnaire sans les extraire dans une for-inboucle?

Stuart
la source
1
Swift 5: colorsForColorSchemes.values
Juan Boero

Réponses:

285

Depuis Swift 2.0, Dictionaryla valuespropriété de renvoie désormais a LazyMapCollectionau lieu de a LazyBidirectionalCollection. Le Arraytype sait comment s'initialiser à l'aide de ce type de collection abstraite:

let colors = Array(colorsForColorSchemes.values)

L'inférence de type de Swift sait déjà que ces valeurs sont des UIColorobjets, donc aucune conversion de type n'est requise, ce qui est bien!

Stuart
la source
1
vous pouvez également le convertir en tableau avec des objets typés. fonctionne très bien! merci let colors = [CustomColorObject] (colorsForColorSchemes.values)
bolnad
6
Il semble que dans Swift 2.0, Dictionary.values ​​renvoie maintenant un LazyMapCollection par opposition à un LazyBidirectionalCollection. Malheureusement, .array n'est pas défini sur un LazyMapCollection. Cependant, la méthode Array (dictionary.values) fonctionne toujours correctement car les types de tableau savent comment s'initialiser à partir d'un LazyMapCollection.
Tod Cunningham
8
Notez que l'ordre des valeurs peut être inattendu. Par exemple [0: "small", 1: "medium", 2: "large"], ne générera probablement PAS["small", "medium", "large"]
Simon Bengtsson
55

Vous pouvez mapper le dictionnaire à un tableau de valeurs:

let colors = colorsForColorScheme.map { $0.1 }

Closure prend un tuple clé-valeur du dictionnaire et ne renvoie qu'une valeur. Ainsi, la fonction de carte produit un tableau de valeurs.

Version plus lisible du même code:

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

METTRE À JOUR

Depuis Xcode 9.0, les valeurs du dictionnaire sont accessibles à l'aide de valuesproperty, qui est conforme au Collectionprotocole:

let colors = colorsForColorScheme.values

En règle générale, vous le voulez simplement sous forme de tableau:

let colors = Array(dict.values)

et c'est tout.

pjuzeliunas
la source
2
Mais en fait, c'est un moyen lisible d'obtenir un tableau let colors = Array (colorsForColorScheme.values)
Renetik
1
aime cette solution
Navy Seal
@pjuzeliunas puisque c'est la meilleure réponse ici, je viens de l'éditer dans le dernier pour 2020. évidemment détendez-vous, éditez, etc.! bravo et merci!
Fattie
10

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

Vishal kundaliya
la source
8

vous pouvez créer une extension sur LazyMapCollection

public extension LazyMapCollection  {

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

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

GSerjo
la source
3

Tout d'abord, d'après l'instruction suivante, il semble que le nom de votre variable (dictionnaire) soit colorsForColorScheme

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

pendant que vous essayez d'obtenir les valeurs du colorsForColorSchemesdictionnaire lorsque vous l'avez fait-

let colors: [UIColor] = colorsForColorSchemes.values

ce qui devrait vous donner une erreur de compilation. Quoi qu'il en soit, je suppose que vous avez eu une faute de frappe, et le nom de votre dictionnaire est colorsForColorSchemes. Alors, voici la solution-

Comme mentionné précédemment, en raison de la propriété d'inférence de type dans swift, votre code peut déduire que le type renvoyé par le .values fonction renvoie un tableau d'UIColor. Cependant, Swift veut être de type sécurisé, donc lorsque vous stockez les valeurs dans le colorstableau, vous devez le définir explicitement. Pour swift 5 et au-dessus, vous pouvez maintenant simplement faire ce qui suit-

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