Swift Dictionary: Werte als Array abrufen

150

Ich habe ein Wörterbuch mit UIColorObjekten, die durch einen Aufzählungswert gehasht wurden ColorScheme:

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

Ich möchte in der Lage sein, ein Array aller Farben (der Werte) zu extrahieren, die in diesem Wörterbuch enthalten sind. Ich dachte, ich könnte die valuesEigenschaft verwenden, wie sie beim Durchlaufen von Wörterbuchwerten ( for value in dictionary.values {...}) verwendet wird, aber dies gibt einen Fehler zurück:

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

Es scheint, dass Arraydie valuesMethode keinen der Werte zurückgibt , sondern einen abstrakteren Auflistungstyp. Gibt es eine Möglichkeit, Arraydie Werte des Wörterbuchs zu erhalten, ohne sie in einer for-inSchleife zu extrahieren ?

Stuart
quelle
1
Swift 5: colorsForColorSchemes.values
Juan Boero

Antworten:

284

Ab Swift 2.0 gibt Dictionarydie valuesEigenschaft von a jetzt a LazyMapCollectionanstelle von a zurück LazyBidirectionalCollection. Der ArrayTyp weiß, wie er sich mit diesem abstrakten Sammlungstyp initialisiert:

let colors = Array(colorsForColorSchemes.values)

Die Typinferenz von Swift weiß bereits, dass diese Werte UIColorObjekte sind, daher ist kein Typumwandeln erforderlich, was sehr schön ist!

Stuart
quelle
1
Sie können es auch als Array mit typisierten Objekten umwandeln. funktioniert super! danke let colours = [CustomColorObject] (coloursForColorSchemes.values)
bolnad
6
Es sieht so aus, als ob in Swift 2.0 Dictionary.values ​​jetzt eine LazyMapCollection im Gegensatz zu einer LazyBidirectionalCollection zurückgibt. Leider ist .array in einer LazyMapCollection nicht definiert. Die Methode Array (dictionary.values) funktioniert jedoch weiterhin einwandfrei, da die Array-Typen wissen, wie sie sich aus einer LazyMapCollection heraus initialisieren.
Tod Cunningham
8
Beachten Sie, dass die Reihenfolge der Werte möglicherweise unerwartet ist. Zum Beispiel [0: "small", 1: "medium", 2: "large"]wird wahrscheinlich NICHT generieren["small", "medium", "large"]
Simon Bengtsson
55

Sie können das Wörterbuch einem Array von Werten zuordnen:

let colors = colorsForColorScheme.map { $0.1 }

Closure nimmt ein Schlüsselwerttupel aus dem Wörterbuch und gibt nur einen Wert zurück. Die Kartenfunktion erzeugt also ein Array von Werten.

Besser lesbare Version des gleichen Codes:

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

AKTUALISIEREN

Ab Xcode 9.0 kann auf Wörterbuchwerte über eine valuesEigenschaft zugegriffen werden , die dem CollectionProtokoll entspricht :

let colors = colorsForColorScheme.values

Normalerweise möchten Sie es nur als Array:

let colors = Array(dict.values)

und das ist es.

pjuzeliunas
quelle
2
Aber tatsächlich ist dies ein lesbarer Weg, um ein Array zu erhalten. Lassen Sie Farben = Array (farbenForColorScheme.values)
Renetik
1
liebe diese Lösung
Navy Seal
@pjuzeliunas da dies die beste Antwort hier ist, habe ich gerade in der neuesten Version für 2020 bearbeitet. Offensichtlich entspannen, bearbeiten usw.! Prost und danke!
Fattie
10

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

Vishal Kundaliya
quelle
8

Sie können eine Erweiterung für erstellen LazyMapCollection

public extension LazyMapCollection  {

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

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

GSerjo
quelle
3

Aus der folgenden Aussage geht zunächst hervor, dass Ihr Variablenname (Wörterbuch) lautet colorsForColorScheme

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

während Sie versuchen, die Werte aus dem colorsForColorSchemesWörterbuch zu erhalten, als Sie dies taten

let colors: [UIColor] = colorsForColorSchemes.values

Dies sollte zu einem Fehler bei der Kompilierung führen. Wie auch immer, ich gehe davon aus, dass Sie einen Tippfehler hatten und Ihr Wörterbuch heißt colorsForColorSchemes. Also, hier ist die Lösung -

Wie bereits erwähnt, kann Ihr Code aufgrund der schnellen Typinferenz-Eigenschaft darauf schließen, dass der von der .valuesFunktion zurückgegebene Typ ein Array von UIColor zurückgibt. Swift möchte jedoch typsicher sein. Wenn Sie also die Werte im colorsArray speichern , müssen Sie dies explizit definieren. Für Swift 5 und höher können Sie jetzt einfach Folgendes tun:

let colors = [UIColor](colorsForColorSchemes.values)
Natascha
quelle