Быстрый словарь: получить значения в виде массива

151

У меня есть словарь, содержащий UIColorобъекты, хэшированные по значению enum 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)

Вывод типа Swift уже знает, что эти значения являются UIColorобъектами, поэтому приведение типов не требуется, и это хорошо!

Стюарт
источник
1
Вы также можете преобразовать его в массив с типизированными объектами. прекрасно работает! спасибо let colors = [CustomColorObject] (colorsForColorSchemes.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)

и это все.

pjuzeliunas
источник
2
Но на самом деле это читабельный способ получить массив let colors = Array (colorsForColorScheme.values)
Renetik
1
люблю это решение
Морской
@pjuzeliunas, так как это лучший ответ здесь, я только что отредактировал последний в 2020 году. очевидно, раскрутите, отредактируйте и т.д.! ура и спасибо!
Толстяк
10

использование colorsForColorScheme.map({$0.value})

Вишал Кундалия
источник
8

Вы можете создать расширение на LazyMapCollection

public extension LazyMapCollection  {

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

colorsForColorSchemes.values.toArray() или colorsForColorSchemes.keys.toArray()

GSerjo
источник
3

Во-первых, из следующего утверждения кажется, что имя вашей переменной (словаря) colorsForColorScheme

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

пока вы пытаетесь получить значения из colorsForColorSchemesсловаря, когда вы

let colors: [UIColor] = colorsForColorSchemes.values

что должно дать вам ошибку времени компиляции. В любом случае, я предполагаю, что у вас была опечатка, и ваш словарь зовут colorsForColorSchemes. Итак, вот решение

Как упоминалось ранее, из-за свойства вывода типа в swift ваш код может сделать вывод, что возвращаемый тип из .valuesфункции возвращает массив UIColor. Однако Swift хочет быть безопасным с точки зрения типов, поэтому, когда вы сохраняете значения в colorsмассиве, вам необходимо явно определить это. Для быстрой 5 и выше, теперь вы можете просто сделать следующее-

let colors = [UIColor](colorsForColorSchemes.values)
Наташа
источник