swift nsset

Cómo crear una matriz de lista de objetos únicos en Swift



nsset (10)

A partir de Swift 1.2 (Xcode 6.3 beta), Swift tiene un tipo de conjunto nativo. De las notas de la versión:

Se incluye una nueva estructura de datos de Set que proporciona una colección genérica de elementos únicos, con semántica de valor completo. Se NSSet con NSSet , proporcionando una funcionalidad análoga a Array y Dictionary .

Aquí hay algunos ejemplos de uso simples:

// 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") }

pero hay muchos más métodos disponibles.

Actualización: los conjuntos ahora también están documentados en el capítulo "Tipos de colección" de la documentación de Swift.

¿Cómo podemos crear una lista de objetos única en lenguaje Swift como NSSet & NSMutableSet en Objective-C?




En realidad, puedes crear un objeto Set bastante fácil (en contradicción con GoZoner, hay un método incorporado que contiene):

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

y quizás quieras declarar un operador personalizado:

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


Escribí una función para resolver este problema.

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

Para usarlo, simplemente pase una matriz que contenga elementos duplicados a esta función. Y luego devolverá una matriz garantizada por exclusividad.

También puede pasar un Dictionary , String o cualquier cosa conforme al protocolo ExtensibleCollectionType si lo desea.


Pensé que una estructura con un diccionario interno sería el camino a seguir. Recién comencé a usarlo, por lo que no está completo y aún no tengo idea de su rendimiento.

struct Set<T : Hashable> { var _items : Dictionary<T, Bool> = [:] 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 } } }


Puedes usar cualquier clase Objective-C en Swift:

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


Siempre en tal caso, el factor crítico es cómo comparar objetos y qué tipos de objetos entran en el Conjunto. Usar un Swift Dictionary, donde los objetos Set son las teclas del diccionario, podría ser un problema basado en las restricciones del tipo de tecla (String, Int, Double, Bool, Enumerations sin valor o hashable).

Si puede definir una función hash en su tipo de objeto, puede usar un diccionario. Si los objetos se pueden ordenar , entonces podrías definir un árbol. Si los objetos son solo comparables con == , necesitarás iterar sobre los elementos establecidos para detectar un objeto preexistente.

// When T is only Equatable class Set<T: Equatable> { var items = Array<T>() 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) } }

Lo anterior es un ejemplo de cómo construir un Swift Set ; el ejemplo usó objetos que son solo Equatable , lo que, si bien es un caso común, no conduce necesariamente a implementaciones de Set eficientes (complejidad de búsqueda O (N)), lo anterior es un ejemplo).


Swift no tiene concepto de conjuntos. Usar NSMutableSet en Swift podría ser más lento que usar un Dictionary que contenga valores ficticios. Podrías hacer esto:

var mySet: Dictionary<String, Boolean> = [:] mySet["something"]= 1

Luego solo itera sobre las teclas.


extension Array where Element: Hashable { var setValue: Set<Element> { return Set<Element>(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"}