Como criar uma matriz de lista de objects exclusivos no Swift

Como podemos criar lista de objects exclusivos na linguagem Swift como NSSet & NSMutableSet em Objective-C.

A partir do Swift 1.2 (Xcode 6.3 beta), o Swift tem um tipo de conjunto nativo. Das notas de lançamento:

Uma nova estrutura de dados Set é incluída, o que fornece uma coleção genérica de elementos exclusivos, com semântica de valor total. Ele faz a ponte com o NSSet , fornecendo funcionalidade análoga ao Array and Dictionary .

Aqui estão alguns exemplos simples de uso:

 // Create set from array literal: var set = Set([1, 2, 3, 2, 1]) // Add single elements: set.insert(4) set.insert(3) // Add multiple elements: set.unionInPlace([ 4, 5, 6 ]) // Swift 3: set.formUnion([ 4, 5, 6 ]) // Remove single element: set.remove(2) // Remove multiple elements: set.subtractInPlace([ 6, 7 ]) // Swift 3: set.subtract([ 6, 7 ]) print(set) // [5, 3, 1, 4] // Test membership: if set.contains(5) { print("yes") } 

mas há muito mais methods disponíveis.

Atualização: Os conjuntos agora também estão documentados no capítulo “Tipos de coleção” da documentação do Swift.

Você pode usar qualquer class Objective-C no Swift:

 var set = NSMutableSet() set.addObject(foo) 

O Swift não tem conceito de conjuntos. Usando NSMutableSet no Swift pode ser mais lento do que usar um Dictionary que contém valores fictícios. Você poderia fazer isso:

 var mySet: Dictionary = [:] mySet["something"]= 1 

Então apenas iterar sobre as chaves.

Eu construí um extenso tipo Set similar ao Array and Dictionary integrado – aqui estão os posts um e dois e um repository GitHub:

  • Criando um tipo de conjunto no Swift
  • Definir acompanhamento de tipo
  • SwiftSets no GitHub
 extension Array where Element: Hashable { var setValue: Set { return Set(self) } } let numbers = [1,2,3,4,5,6,7,8,9,0,0,9,8,7] let uniqueNumbers = numbers.setValue // {0, 2, 4, 9, 5, 6, 7, 3, 1, 8} let names = ["John","Mary","Steve","Mary"] let uniqueNames = names.setValue // {"John", "Mary", "Steve"} 

Eu pensei que uma estrutura com um dictionary interno seria o caminho a percorrer. Eu acabei de começar a usá-lo, então não está completo e ainda não tenho idéia do desempenho.

 struct Set { var _items : Dictionary = [:] mutating func add(newItem : T) { _items[newItem] = true } mutating func remove(newItem : T) { _items[newItem] = nil } func contains(item: T) -> Bool { if _items.indexForKey(item) != nil { return true } else { return false } } var items : [T] { get { return [T](_items.keys) } } var count : Int { get { return _items.count } } } 

Você pode criar um object Set muito fácil (em contradição com o GoZoner, existe um método contains):

 class Set { var items : T[] = [] func add(item : T) { if !contains(items, {$0 == item}) { items += item } } } 

e talvez você queira declarar um operador personalizado:

 @assignment @infix func +=  (inout set : Set, items : T[]) -> Set { for item in items { set.add(item) } return set } 

Sempre nesse caso, o fator crítico é como comparar objects e quais tipos de objects entram no Conjunto. Usar um Swift Dictionary, onde os objects Set são as chaves do dictionary, pode ser um problema com base nas restrições do tipo de chave (String, Int, Double, Bool, Enumerações sem valor ou hashable).

Se você pode definir uma function hash no seu tipo de object, então você pode usar um Dicionário. Se os objects forem ordenados , você poderá definir uma Árvore. Se os objects forem comparáveis ​​apenas com == , será necessário iterar os elementos do conjunto para detectar um object preexistente.

 // When T is only Equatable class Set { var items = Array() func hasItem (that: T) { // No builtin Array method of hasItem... // because comparison is undefined in builtin Array for this: T in items { if (this == that) { return true } } return false } func insert (that: T) { if (!hasItem (that)) items.append (that) } } 

O acima é um exemplo de construção de um Set Swift; o exemplo usou objects que são apenas Equatable – o que, embora seja um caso comum, não leva necessariamente a uma eficiente implementação de Set (O (N) – o exemplo acima).

Então eu acho que criar um Set com um array é uma idéia terrível – O (n) é a complexidade de tempo desse conjunto.

Eu coloquei um conjunto agradável que usa um dictionary: https://github.com/evilpenguin/Swift-Stuff/blob/master/Set.swift

Eu escrevi uma function para resolver esse problema.

 public func removeDuplicates(aCollection: C) -> C { var container = C() for element in aCollection { if !contains(container, element) { container.append(element) } } return container } 

Para usá-lo, basta passar um array que contém elementos duplicados para esta function. E então, ele retornará um array com exclusividade garantida.

Você também pode passar um Dictionary , String ou qualquer coisa que esteja de acordo com o protocolo ExtensibleCollectionType , se desejar.

    Intereting Posts