Objetos únicos dentro de un arreglo Swift

Tengo una matriz, con objects personalizados.

Me gustaría hacer estallar los objects repetidos, con las properties repetidas:

let product = Product() product.subCategory = "one" let product2 = Product() product2.subCategory = "two" let product3 = Product() product3.subCategory = "two" let array = [product,product2,product3] 

en este caso, product2 or product3 estallar el product2 or product3

Puedes usar Swift Set :

 let array = [product,product2,product3] let set = Set(array) 

Tienes que hacer que el Product ajuste a Hashable (y por lo tanto, Equatable ) sin embargo:

 class Product : Hashable { var subCategory = "" var hashValue: Int { return subCategory.hashValue } } func ==(lhs: Product, rhs: Product) -> Bool { return lhs.subCategory == rhs.subCategory } 

Y, si el Product era una subclass NSObject , debe anular isEqual :

 override func isEqual(object: AnyObject?) -> Bool { if let product = object as? Product { return product == self } else { return false } } 

Claramente, modifíquelos para reflejar otras properties que pueda tener en su class. Por ejemplo:

 class Product : Hashable { var category = "" var subCategory = "" var hashValue: Int { return [category, subCategory].hashValue } } func ==(lhs: Product, rhs: Product) -> Bool { return lhs.category == rhs.category && lhs.subCategory == rhs.subCategory } 

Si el Product ajusta a Equatable , donde un producto es igual en function de su subcategoría (y no le importa el order), puede agregar los objects a un set y tomar una matriz de ese set:

 let array = [product,product2,product3] let set = NSSet(array: array) let uniqueArray = set.allObjects 

o

 let array = [product,product2,product3] let set = Set(array) let uniqueArray = Array(set) 

Si su class cumple con el protocolo Hashable y desea mantener el order de la matriz original, puede crear una extensión como sigue:

 extension Array where Element: Hashable { var uniqueElements: [Element] { var elements: [Element] = [] for element in self { if let _ = elements.indexOf(element) { print("item found") } else { print("item not found, add it") elements.append(element) } } return elements } } 
 class Product { var subCategory: String = "" } let product = Product() product.subCategory = "one" let product2 = Product() product2.subCategory = "two" let product3 = Product() product3.subCategory = "two" let array = [product,product2,product3] extension Product : Hashable { var hashValue: Int { return subCategory.hashValue } } func ==(lhs: Product, rhs: Product)->Bool { return lhs.subCategory == rhs.subCategory } let set = Set(array) set.forEach { (p) -> () in print(p, p.subCategory) } /* Product one Product two */ 

si un elemento es parte del set o no, no depende de hashValue, depende de la comparación. Si su producto cumple con Hashable, debe cumplir con Equatable. si necesita que la creación del set dependa únicamente de la subcategoría, la comparación debería depender únicamente de la subcategoría. esto puede ser un gran problema, si necesita comparar sus productos de alguna otra manera

Aquí hay una extensión de matriz para devolver la list única de objects basada en una key determinada:

 extension Array { func unique<T:Hashable>(map: ((Element) -> (T))) -> [Element] { var set = Set<T>() //the unique list kept in a Set for fast retrieval var arrayOrdenetworking = [Element]() //keeping the unique list of elements but ordenetworking for value in self { if !set.contains(map(value)) { set.insert(map(value)) arrayOrdenetworking.append(value) } } return arrayOrdenetworking } } 

usando esto puedes hacerlo así

 let unique = [product,product2,product3].unique{$0.subCategory} 

esto tiene la ventaja de no requerir el Hashable y de poder devolver una list única basada en cualquier campo o combinación