Swift definido como matriz

187

Um NSSetpode ser convertido para Arrayuso, set.allObjects()mas não existe esse método no novo Set(introduzido no Swift 1.2). Isso ainda pode ser feito convertendo o Swift Set para NSSet e use o allObjects()método, mas isso não é o ideal.

Arroz frito
fonte

Respostas:

352

Você pode criar uma matriz com todos os elementos de um determinado Swift Setsimplesmente com

let array = Array(someSet)

Isso funciona porque Setestá em conformidade com o SequenceTypeprotocolo e Arraypode ser inicializado com uma sequência. Exemplo:

let mySet = Set(["a", "b", "a"])  // Set<String>
let myArray = Array(mySet)        // Array<String>
print(myArray) // [b, a]
Martin R
fonte
4
Como uma nota lateral, let array = Array(someSet)também trabalha na Swift 2
Suragch
... ou deixe myArray = myNSSet.allObjects as! [mySpecificType]
angelos.p 13/12/15
3
@plusangel: Sim, se NSSetfor fornecido. A pergunta era sobre um Swift Set.
Martin R
@KendallHelmstetterGelner: Verifiquei duas vezes o exemplo de código acima com o Swift 2.3 e o Swift 3. Ele compilou e funcionou conforme o esperado para mim. Que erro você recebe?
Martin R
@ MartinR Interessante, eu estava tentando fazer isso com um conjunto de um relacionamento NSManagedObject, e ele não gostou do construtor Array na época - agora que tento reproduzir o problema, não posso. Eu tenho que adicionar o rótulo "arrayLiteral:" no construtor Array. Eu removi meu comentário anterior para não confundir ninguém, obrigado por verificar! Eu não sei por que o guia Swift não tem esta forma de conversão ...
Kendall Helmstetter Gelner
21

No caso mais simples , com o Swift 3, você pode usar Arrayo init(_:)inicializador para obter um Arrayde a Set. init(_:)tem a seguinte declaração:

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

Cria uma matriz que contém os elementos de uma sequência.

Uso:

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

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

No entanto , se você também quiser executar algumas operações em cada elemento do seu Setenquanto transformando-o em um Array, você pode usar map, flatMap, sort, filtere outros métodos funcionais previstos pelo Collectionprotocolo:

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]
Imanou Petit
fonte
Usando um desses métodos, posso criar uma matriz opcional a partir de um conjunto opcional.
tzaloga
11

ADIÇÃO :

Swift não possui ORDEM DEFINIDA para Conjunto e Dicionário. Por esse motivo, você deve usar o método classificado () para impedir a obtenção de resultados inesperados, como sua matriz, pode ser como ["a", "b"] ou ["b", "a "] e você não quer isso.

Para corrigir isso:

PARA CONJUNTOS

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

Resultado: ["a", "b", "c"]

Sem classificado ()

Pode ser:

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

matemática simples: 3! = 6


fonte
10

Eu criei uma extensão simples que fornece Arrayuma propriedade não classificada como Setno Swift 4.0 .

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

Se você deseja uma matriz classificada, pode adicionar uma propriedade computada adicional ou modificar a existente para atender às suas necessidades.

Para usar isso, basta ligar

let array = set.array
CodeBender
fonte
3

A resposta atual para o Swift 2.xe superior (do guia Swift Programming Language sobre Tipos de coleção) parece ser uma iteração sobre as entradas do conjunto da seguinte maneira:

for item in myItemSet {
   ...
}

Ou, para usar o método "classificado":

let itemsArray = myItemSet.sorted()

Parece que os designers do Swift não gostaram de allObjects como um mecanismo de acesso porque Sets não são realmente ordenados, então eles queriam garantir que você não saísse de uma matriz sem uma ordem explícita aplicada.

Se você não deseja a sobrecarga da classificação e não se importa com a ordem, normalmente uso os métodos map ou flatMap, que devem ser um pouco mais rápidos para extrair uma matriz:

let itemsArray = myItemSet.map { $0 }

O que criará uma matriz do tipo que o conjunto mantém; se você precisar de uma matriz de um tipo específico (digamos, direitos de um conjunto de relações de objeto gerenciado que não são declaradas como um conjunto digitado), você pode fazer algo como:

var itemsArray : [MyObjectType] = []
if let typedSet = myItemSet as? Set<MyObjectType> {
 itemsArray = typedSet.map { $0 }
}
Kendall Helmstetter Gelner
fonte
myItemSet.sorted()requer que os elementos sejam Comparable. - myItemSet.map { $0 }deve produzir o mesmo resultado que Array(myItemSet), ambos criam uma matriz enumerando todos os elementos do conjunto. O último ainda funciona para mim, alguns detalhes sobre o seu comentário acima seriam apreciados.
Martin R
-2

chame esse método e passe seu conjunto

func getArrayFromSet(set:NSSet)-> NSArray {

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

Como isso :

var letters:Set = Set<String>(arrayLiteral: "test","test") // your set
print(self.getArrayFromSet(letters))
Shubham bairagi
fonte
2
Use Array (<Set>) é uma escolha melhor
Sébastien REMY