Swift réglé sur Array


187

An NSSetpeut être converti en Arrayutilisation, set.allObjects()mais il n'existe pas de méthode de ce type dans le nouveau Set(introduit avec Swift 1.2). Cela peut toujours être fait en convertissant Swift Set en NSSet et en utilisant la allObjects()méthode, mais ce n'est pas optimal.

Réponses:


352

Vous pouvez créer un tableau avec tous les éléments d'un Swift donné Setsimplement avec

let array = Array(someSet)

Cela fonctionne car Setest conforme au SequenceTypeprotocole et Arraypeut être initialisé avec une séquence. Exemple:

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

4
En remarque, let array = Array(someSet)fonctionne également dans Swift 2
Suragch

... ou laissez myArray = myNSSet.allObjects as! [mySpecificType]
angelos.p

3
@plusangel: Oui, si un NSSetest donné. La question portait sur un Swift Set.
Martin R

@KendallHelmstetterGelner: J'ai revérifié l'exemple de code ci-dessus avec Swift 2.3 et Swift 3. Il a été compilé et a fonctionné comme prévu pour moi. Quelle erreur obtenez-vous?
Martin R

@MartinR Intéressant, je l'essayais avec un ensemble issu d'une relation NSManagedObject, et il n'aimait pas le constructeur Array à l'époque - maintenant que j'essaye de reproduire le problème, je ne peux pas. Je dois cependant ajouter l'étiquette "arrayLiteral:" dans le constructeur Array. J'ai supprimé mon commentaire précédent pour ne confondre personne, merci de vérifier! Je ne sais pas pourquoi le guide Swift n'a pas ce formulaire de conversion ...
Kendall Helmstetter Gelner

21

Dans le cas le plus simple , avec Swift 3, vous pouvez utiliser Arrayl' init(_:)initialiseur de pour obtenir un Arraydepuis a Set. init(_:)a la déclaration suivante:

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

Crée un tableau contenant les éléments d'une séquence.

Usage:

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

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

Cependant , si vous souhaitez également effectuer certaines opérations sur chaque élément de votre Settout en le transformant en un Array, vous pouvez utiliser map, flatMap, sort, filteret d' autres méthodes fonctionnelles fournies par le Collectionprotocole:

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]

En utilisant l'une de ces méthodes, je peux créer un tableau facultatif à partir d'un ensemble facultatif.
tzaloga le

11

UNE ADDITION :

Swift n'a pas d' ORDRE DÉFINI pour Set et Dictionary. Pour cette raison, vous devriez utiliser la méthode sorted () pour éviter d'obtenir des résultats inattendus tels que votre tableau peut être comme ["a", "b"] ou ["b", "a "] et vous ne le voulez pas.

POUR RÉPARER CECI:

POUR ENSEMBLES

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

Résultat: ["a", "b", "c"]

Sans trié ()

Ça peut être:

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

maths simples: 3! = 6


10

J'ai créé une simple extension qui vous donne Arrayune propriété non triée Setdans Swift 4.0 .

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

Si vous souhaitez un tableau trié, vous pouvez soit ajouter une propriété calculée supplémentaire, soit modifier celle existante en fonction de vos besoins.

Pour l'utiliser, il suffit d'appeler

let array = set.array

3

La réponse actuelle pour Swift 2.x et supérieur (du guide du langage de programmation Swift sur les types de collections) semble être d'itérer sur les entrées de l'ensemble comme ceci:

for item in myItemSet {
   ...
}

Ou, pour utiliser la méthode "triée":

let itemsArray = myItemSet.sorted()

Il semble que les concepteurs de Swift n'aimaient pas allObjects comme mécanisme d'accès car les ensembles ne sont pas vraiment ordonnés, ils voulaient donc s'assurer que vous ne sortiez pas d'un tableau sans qu'un ordre explicite ne soit appliqué.

Si vous ne voulez pas la surcharge du tri et que vous ne vous souciez pas de l'ordre, j'utilise généralement les méthodes map ou flatMap qui devraient être un peu plus rapides pour extraire un tableau:

let itemsArray = myItemSet.map { $0 }

Ce qui construira un tableau du type que l'ensemble contient, si vous en avez besoin pour être un tableau d'un type spécifique (par exemple, des droits à partir d'un ensemble de relations d'objets gérés qui ne sont pas déclarés comme un ensemble typé), vous pouvez faire quelque chose comme:

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

myItemSet.sorted()exige que les éléments soient Comparable. - myItemSet.map { $0 }devrait produire le même résultat que Array(myItemSet), les deux créent un tableau en énumérant tous les éléments de l'ensemble. Ce dernier fonctionne toujours pour moi, quelques détails sur votre commentaire ci-dessus seraient appréciés.
Martin R

-2

appelez cette méthode et passez votre set

func getArrayFromSet(set:NSSet)-> NSArray {

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

Comme ça :

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

2
Utiliser Array (<Set>) est un meilleur choix
Sébastien REMY
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.