Swift Set to Array


187

An NSSetможно преобразовать в Arrayиспользование, set.allObjects()но в новом методе такого нет Set(введено в Swift 1.2). Это все еще может быть сделано путем преобразования набора Swift в NSSet и использования allObjects()метода, но это не является оптимальным.

Ответы:


352

Вы можете создать массив со всеми элементами из данного Swift Setпросто с помощью

let array = Array(someSet)

Это работает, потому что Setсоответствует SequenceTypeпротоколу и Arrayможет быть инициализирован последовательностью. Пример:

let mySet = Set(["a", "b", "a"])  // Set<String>
let myArray = Array(mySet)        // Array<String>
print(myArray) // [b, a]

4
Как примечание стороны, let array = Array(someSet)также работает в Swift 2
Suragch

... или пусть myArray = myNSSet.allObjects как! [mySpecificType]
angelos.p

3
@plusangel: Да, если NSSetдано. Вопрос был о Свифте Set.
Мартин Р

@KendallHelmstetterGelner: Я дважды проверил приведенный выше пример кода и с Swift 2.3, и с Swift 3. Он скомпилирован и работает, как и ожидалось. Какая у вас ошибка?
Мартин Р

@MartinR Интересно, я пробовал это с набором из отношения NSManagedObject, и в то время мне не нравился конструктор Array - теперь, когда я пытаюсь воспроизвести проблему, я не могу. Я должен добавить метку "arrayLiteral:" в конструктор Array. Я удалил свой предыдущий комментарий, чтобы он никого не смутил, спасибо за проверку! Я не знаю, почему у руководства Свифта нет этой конверсионной формы ...
Кендалл Хельмштеттер Гелнер

21

В простейшем случае , с Swift 3, вы можете использовать Array«s init(_:)инициализатор , чтобы получить Arrayот Set. init(_:)имеет следующую декларацию:

init<S>(_ s: S) where S : Sequence, Element == S.Iterator.Element

Создает массив, содержащий элементы последовательности.

Использование:

let stringSet = Set(arrayLiteral: "car", "boat", "car", "bike", "toy")    
let stringArray = Array(stringSet)

print(stringArray)
// may print ["toy", "car", "bike", "boat"]

Тем не менее , если вы хотите , чтобы выполнить некоторые операции по каждому элементу вашего Setпри преобразовании его в Array, вы можете использовать map, flatMap, sort, filterи другие функциональные методы , предоставляемые Collectionпротоколом:

let stringSet = Set(["car", "boat", "bike", "toy"])
let stringArray = stringSet.sorted()

print(stringArray)
// will print ["bike", "boat", "car", "toy"]
let stringSet = Set(arrayLiteral: "car", "boat", "car", "bike", "toy") 
let stringArray = stringSet.filter { $0.characters.first != "b" }

print(stringArray)
// may print ["car", "toy"]
let intSet = Set([1, 3, 5, 2]) 
let stringArray = intSet.flatMap { String($0) }

print(stringArray)
// may print ["5", "2", "3", "1"]
let intSet = Set([1, 3, 5, 2])
// alternative to `let intArray = Array(intSet)`
let intArray = intSet.map { $0 }

print(intArray)
// may print [5, 2, 3, 1]

Используя один из этих методов, я могу сделать необязательный массив из необязательного набора.
Цалога

11

ДОПОЛНЕНИЕ:

У Swift нет ЗАДАННОГО ЗАКАЗА для Set и Dictionary. По этой причине вы должны использовать метод sorted (), чтобы предотвратить получение неожиданных результатов, например, ваш массив может иметь вид ["a", "b"] или ["b", "a "] и вы не хотите этого.

ЧТОБЫ ИСПРАВИТЬ ЭТО:

ДЛЯ КОМПЛЕКТОВ

var example:Set = ["a","b","c"]
let makeExampleArray = [example.sorted()]
makeExampleArray 

Результат: ["a", "b", "c"]

Без сортировки ()

Может быть:

["a","b","c"] or ["b","c","a",] or ["c","a","b"] or ["a","c","b"] or ["b","a","c"] or ["c","b","a"] 

простая математика: 3! = 6


10

Я создал простое расширение, которое дает вам несортированное Arrayсвойство Setв Swift 4.0 .

extension Set {
    var array: [Element] {
        return Array(self)
    }
}

Если вы хотите отсортированный массив, вы можете добавить дополнительное вычисляемое свойство или изменить существующее в соответствии с вашими потребностями.

Чтобы использовать это, просто позвоните

let array = set.array

3

Текущий ответ для Swift 2.x и выше (из руководства по языку программирования Swift по типам коллекций), по-видимому, заключается в переборе записей Set, например:

for item in myItemSet {
   ...
}

Или использовать «отсортированный» метод:

let itemsArray = myItemSet.sorted()

Похоже, что разработчикам Swift не понравились allObjects как механизм доступа, потому что множества на самом деле не упорядочены, поэтому они хотели убедиться, что вы не получили массив без применения явного упорядочения.

Если вы не хотите накладных расходов на сортировку и не заботитесь о порядке, я обычно использую методы map или flatMap, которые должны быть немного быстрее для извлечения массива:

let itemsArray = myItemSet.map { $0 }

Который будет создавать массив типа, который содержит Set, если вам нужно, чтобы он был массивом определенного типа (скажем, дает права из набора отношений управляемых объектов, которые не объявлены как типизированный набор), вы можете сделать что-то вроде:

var itemsArray : [MyObjectType] = []
if let typedSet = myItemSet as? Set<MyObjectType> {
 itemsArray = typedSet.map { $0 }
}

myItemSet.sorted()требует, чтобы элементы были Comparable. - myItemSet.map { $0 }должен выдать тот же результат, что Array(myItemSet)и оба, создать массив путем перечисления всех элементов набора. Последнее все еще работает для меня, некоторые детали вашего комментария будут оценены.
Мартин Р

-2

вызвать этот метод и передать свой набор

func getArrayFromSet(set:NSSet)-> NSArray {

return set.map ({ String($0) })
}

Как это :

var letters:Set = Set<String>(arrayLiteral: "test","test") // your set
print(self.getArrayFromSet(letters))

2
Использование Array (<Set>) - лучший выбор
Себастьян РЕМИ
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.