Swift Dictionary: Отримайте значення у вигляді масиву


151

У мене є словник , що містить UIColorоб'єкти з допомогою хеш - значення перерахування, ColorScheme:

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'

Здається, що замість повернення Arrayзначень, valuesметод повертає більш абстрактний тип колекції. Чи існує спосіб отримати Arrayзначення словника без вилучення їх у for-inциклі?


1
Свіфт 5: colorsForColorSchemes.values
Хуан Боро

Відповіді:


285

Як Свіфт 2.0 Dictionary«s valuesвластивість тепер повертає LazyMapCollectionзамість LazyBidirectionalCollection. ArrayТип знає , як форматувати себе , використовуючи цей абстрактний тип колекції:

let colors = Array(colorsForColorSchemes.values)

Висновок типу Свіфта вже знає, що ці значення є UIColorоб'єктами, тому не потрібно проводити лиття типів, що приємно!


1
Ви також можете передавати його як масив із типізованими об'єктами. працює чудово! спасибі, нехай кольори = [CustomColorObject] (colorForColorSchemes.values)
бонад

6
Схоже, у Swift 2.0, Dictionary.values ​​тепер повертає LazyMapCollection на відміну від LazyBidirectionalCollection. На жаль, .array не визначений у LazyMapCollection. Однак спосіб Array (dictionary.values) все ще працює чудово, оскільки типи масивів знають, як ініціалізуватися з LazyMapCollection.
Тод Каннінгем,

8
Зауважте, що порядок значень може бути несподіваним. Наприклад [0: "small", 1: "medium", 2: "large"], напевно НЕ породжує["small", "medium", "large"]
Саймон Бенгтссон,

55

Ви можете зіставити словник на масив значень:

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)

і це все.


2
Але насправді це читабельний спосіб отримати масив нехай кольори = Array (colorForColorScheme.values)
Renetik

1
люблю це рішення
Navy Seal

@pjuzeliunas, оскільки це найкраща відповідь тут, я щойно відредагував останній на 2020 рік. привіт і спасибі!
Фетті


8

ви можете створити розширення на LazyMapCollection

public extension LazyMapCollection  {

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

colorsForColorSchemes.values.toArray() або colorsForColorSchemes.keys.toArray()


3

По-перше, з наступного твердження виходить, що назва вашої змінної (словник) є colorsForColorScheme

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

поки ви намагаєтеся отримати значення зі colorsForColorSchemesсловника, коли ви зробили це,

let colors: [UIColor] = colorsForColorSchemes.values

який повинен дати вам помилку часу компіляції. У будь-якому випадку я припускаю, що у вас був помилковий помилок, і ви називаєте словникcolorsForColorSchemes . Отже, ось рішення -

Як згадувалося раніше, через властивість виводу типу у швидкому режимі ваш код може зробити висновок про те, що повернений тип з .valuesфункції повертає масив UIColor. Однак Swift хоче бути безпечним для типу, тому коли ви зберігаєте значення в colorsмасиві, вам потрібно це чітко визначити. Для швидких 5 і вище, тепер ви можете просто виконати наступні дії:

let colors = [UIColor](colorsForColorSchemes.values)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.