arrays - for - Eliminar elementos duplicados de una matriz en Swift
swift array filter (30)
Swift 4.2 probado
extension Sequence where Iterator.Element: Hashable {
func unique() -> [Iterator.Element] {
var seen: [Iterator.Element: Bool] = [:]
return self.filter { seen.updateValue(true, forKey: $0) == nil }
}
}
Podría tener una matriz similar a la siguiente:
[1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
O, realmente, cualquier secuencia de porciones de datos de tipo similar. Lo que quiero hacer es asegurarme de que solo haya uno de cada elemento idéntico. Por ejemplo, la matriz anterior se convertiría en:
[1, 4, 2, 6, 24, 15, 60]
Observe que los duplicados de 2, 6 y 15 se eliminaron para asegurarse de que solo hubiera uno de cada elemento idéntico. ¿Swift proporciona una manera de hacer esto fácilmente, o tendré que hacerlo yo mismo?
rápido 2
con respuesta de función uniq :
func uniq<S: SequenceType, E: Hashable where E==S.Generator.Element>(source: S) -> [E] {
var seen: [E:Bool] = [:]
return source.filter({ (v) -> Bool in
return seen.updateValue(true, forKey: v) == nil
})
}
utilizar:
var test = [1,2,3,4,5,6,7,8,9,9,9,9,9,9]
print(uniq(test)) //1,2,3,4,5,6,7,8,9
- Primero agregue todos los elementos de una matriz a NSOrderedSet.
- Esto eliminará todos los duplicados en su matriz.
- Nuevamente convierta este conjunto ordenado en una matriz.
Hecho....
Ejemplo
let array = [1,1,1,1,2,2,2,2,4,6,8]
let orderedSet : NSOrderedSet = NSOrderedSet(array: array)
let arrayWithoutDuplicates : NSArray = orderedSet.array as NSArray
salida de arrayWithoutDuplicates - [1,2,4,6,8]
Aquí he hecho alguna solución O (n) para objetos. No es una solución de pocas líneas, pero ...
struct DistinctWrapper <T>: Hashable {
var underlyingObject: T
var distinctAttribute: String
var hashValue: Int {
return distinctAttribute.hashValue
}
}
func distinct<S : SequenceType, T where S.Generator.Element == T>(source: S,
distinctAttribute: (T) -> String,
resolution: (T, T) -> T) -> [T] {
let wrappers: [DistinctWrapper<T>] = source.map({
return DistinctWrapper(underlyingObject: $0, distinctAttribute: distinctAttribute($0))
})
var added = Set<DistinctWrapper<T>>()
for wrapper in wrappers {
if let indexOfExisting = added.indexOf(wrapper) {
let old = added[indexOfExisting]
let winner = resolution(old.underlyingObject, wrapper.underlyingObject)
added.insert(DistinctWrapper(underlyingObject: winner, distinctAttribute: distinctAttribute(winner)))
} else {
added.insert(wrapper)
}
}
return Array(added).map( { return $0.underlyingObject } )
}
func == <T>(lhs: DistinctWrapper<T>, rhs: DistinctWrapper<T>) -> Bool {
return lhs.hashValue == rhs.hashValue
}
// tests
// case : perhaps we want to get distinct addressbook list which may contain duplicated contacts like Irma and Irma Burgess with same phone numbers
// solution : definitely we want to exclude Irma and keep Irma Burgess
class Person {
var name: String
var phoneNumber: String
init(_ name: String, _ phoneNumber: String) {
self.name = name
self.phoneNumber = phoneNumber
}
}
let persons: [Person] = [Person("Irma Burgess", "11-22-33"), Person("Lester Davidson", "44-66-22"), Person("Irma", "11-22-33")]
let distinctPersons = distinct(persons,
distinctAttribute: { (person: Person) -> String in
return person.phoneNumber
},
resolution:
{ (p1, p2) -> Person in
return p1.name.characters.count > p2.name.characters.count ? p1 : p2
}
)
// distinctPersons contains ("Irma Burgess", "11-22-33") and ("Lester Davidson", "44-66-22")
En Swift 3.0, la solución más simple y rápida que he encontrado para eliminar los elementos duplicados manteniendo el orden:
extension Array where Element:Hashable {
var unique: [Element] {
var set = Set<Element>() //the unique list kept in a Set for fast retrieval
var arrayOrdered = [Element]() //keeping the unique list of elements but ordered
for value in self {
if !set.contains(value) {
set.insert(value)
arrayOrdered.append(value)
}
}
return arrayOrdered
}
}
Esta es solo una implementación muy simple y conveniente. Una propiedad calculada en una extensión de una matriz que tiene elementos equiparables.
extension Array where Element: Equatable {
/// Array containing only _unique_ elements.
var unique: [Element] {
var result: [Element] = []
for element in self {
if !result.contains(element) {
result.append(element)
}
}
return result
}
}
He hecho una extensión lo más simple posible para ese propósito.
extension Array where Element: Equatable {
func containsHowMany(_ elem: Element) -> Int {
return reduce(0) { $1 == elem ? $0 + 1 : $0 }
}
func duplicatesRemoved() -> Array {
return self.filter { self.containsHowMany($0) == 1 }
}
mutating func removeDuplicates() {
self = self.duplicatesRemoved(()
}
}
Puede usar
duplicatesRemoved()
para obtener una nueva matriz, cuyos elementos duplicados se eliminan, o
removeDuplicates()
para mutar a sí misma.
Ver:
let arr = [1, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 6, 6, 7, 8]
let noDuplicates = arr.duplicatesRemoved()
print(arr) // [1, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 6, 6, 7, 8]
print(noDuplicates) // [1, 2, 3, 4, 5, 6, 7, 8]
arr.removeDuplicates()
print(arr) // [1, 2, 3, 4, 5, 6, 7, 8]
Permítanme sugerir una respuesta similar a la respuesta de Scott Gardner pero con más sintaxis lacónica usando reduce. Esta solución elimina duplicados de una matriz de objetos personalizados (manteniendo el orden inicial)
// Custom Struct. Can be also class.
// Need to be `equitable` in order to use `contains` method below
struct CustomStruct : Equatable {
let name: String
let lastName : String
}
// conform to Equatable protocol. feel free to change the logic of "equality"
func ==(lhs: CustomStruct, rhs: CustomStruct) -> Bool {
return (lhs.name == rhs.name && lhs.lastName == rhs.lastName)
}
let categories = [CustomStruct(name: "name1", lastName: "lastName1"),
CustomStruct(name: "name2", lastName: "lastName1"),
CustomStruct(name: "name1", lastName: "lastName1")]
print(categories.count) // prints 3
// remove duplicates (and keep initial order of elements)
let uniq1 : [CustomStruct] = categories.reduce([]) { $0.contains($1) ? $0 : $0 + [$1] }
print(uniq1.count) // prints 2 - third element has removed
Y solo si se pregunta cómo funciona esta reducción mágica, aquí es exactamente lo mismo, pero con una sintaxis de reducción más expandida
let uniq2 : [CustomStruct] = categories.reduce([]) { (result, category) in
var newResult = result
if (newResult.contains(category)) {}
else {
newResult.append(category)
}
return newResult
}
uniq2.count // prints 2 - third element has removed
Simplemente puede copiar y pegar este código en un Swift Playground y jugar.
Piensa como un programador funcional :)
Para filtrar la lista en función de si el elemento ya ha ocurrido, necesita el índice.
Puede usar
enumerated
para obtener el índice y
map
volver a la lista de valores.
let unique = myArray
.enumerated()
.filter{ myArray.firstIndex(of: $0.1) == $0.0 }
.map{ $0.1 }
Esto garantiza el pedido.
Si no le importa el orden, la respuesta existente
Array(Set(myArray))
es más simple y probablemente más eficiente.
Siempre puede usar un Diccionario, porque un Diccionario solo puede contener valores únicos. Por ejemplo:
var arrayOfDates: NSArray = ["15/04/01","15/04/01","15/04/02","15/04/02","15/04/03","15/04/03","15/04/03"]
var datesOnlyDict = NSMutableDictionary()
var x = Int()
for (x=0;x<(arrayOfDates.count);x++) {
let date = arrayOfDates[x] as String
datesOnlyDict.setValue("foo", forKey: date)
}
let uniqueDatesArray: NSArray = datesOnlyDict.allKeys // uniqueDatesArray = ["15/04/01", "15/04/03", "15/04/02"]
println(uniqueDatesArray.count) // = 3
Como puede ver, la matriz resultante no siempre estará en ''orden''. Si desea ordenar / ordenar la matriz, agregue esto:
var sortedArray = sorted(datesOnlyArray) {
(obj1, obj2) in
let p1 = obj1 as String
let p2 = obj2 as String
return p1 < p2
}
println(sortedArray) // = ["15/04/01", "15/04/02", "15/04/03"]
.
Utilicé la respuesta de @ Jean-Philippe Pellet e hice una extensión de matriz que realiza operaciones similares a conjuntos en matrices, manteniendo el orden de los elementos.
/// Extensions for performing set-like operations on lists, maintaining order
extension Array where Element: Hashable {
func unique() -> [Element] {
var seen: [Element:Bool] = [:]
return self.filter({ seen.updateValue(true, forKey: $0) == nil })
}
func subtract(takeAway: [Element]) -> [Element] {
let set = Set(takeAway)
return self.filter({ !set.contains($0) })
}
func intersect(with: [Element]) -> [Element] {
let set = Set(with)
return self.filter({ set.contains($0) })
}
}
Aquí hay una categoría en
SequenceType
que conserva el orden original de la matriz, pero utiliza un
Set
para realizar las búsquedas de contenido para evitar el costo
O(n)
en el método
contains(_:)
.
public extension Array where Element: Hashable {
/// Return the array with all duplicates removed.
///
/// i.e. `[ 1, 2, 3, 1, 2 ].uniqued() == [ 1, 2, 3 ]`
///
/// - note: Taken from .com/a/46354989/3141234, as
/// per @Alexander''s comment.
public func uniqued() -> [Element] {
var seen = Set<Element>()
return self.filter { seen.insert($0).inserted }
}
}
o si no tienes Hashable, puedes hacer esto:
public extension Sequence where Iterator.Element: Equatable {
public func uniqued() -> [Iterator.Element] {
var buffer: [Iterator.Element] = []
for element in self {
guard !buffer.contains(element) else { continue }
buffer.append(element)
}
return buffer
}
}
Puede pegar ambos en su aplicación, Swift elegirá el correcto dependiendo del
Iterator.Element
su secuencia. Tipo de elemento.
En Swift 5
var array: [String] = ["Aman", "Sumit", "Aman", "Sumit", "Mohan", "Mohan", "Amit"]
let uniq = Array(Set(array))
print(uniq)
La salida será
["Sumit", "Mohan", "Amit", "Aman"]
En caso de que necesite ordenar los valores, esto funciona (Swift 4)
let sortedValues = Array(Set(array)).sorted()
Esto toma parte de la buena información que ya está en esta página, y aplica el enfoque Hashable / Set cuando sea posible, y de lo contrario recurre al código Equatable.
Cambio Swift 4 para la extensión
Hashable
(
Hashable
permanece igual)
public extension Sequence where Element: Equatable {
var uniqueElements: [Element] {
return self.reduce(into: []) {
uniqueElements, element in
if !uniqueElements.contains(element) {
uniqueElements.append(element)
}
}
}
}
Swift 3
public extension Sequence where Iterator.Element: Hashable {
var uniqueElements: [Iterator.Element] {
return Array( Set(self) )
}
}
public extension Sequence where Iterator.Element: Equatable {
var uniqueElements: [Iterator.Element] {
return self.reduce([]){
uniqueElements, element in
uniqueElements.contains(element)
? uniqueElements
: uniqueElements + [element]
}
}
}
Swift 2
public extension SequenceType where Generator.Element: Hashable {
var uniqueElements: [Generator.Element] {
return Array(
Set(self)
)
}
}
public extension SequenceType where Generator.Element: Equatable {
var uniqueElements: [Generator.Element] {
return self.reduce([]){uniqueElements, element in
uniqueElements.contains(element)
? uniqueElements
: uniqueElements + [element]
}
}
}
Inspirado por https://www.swiftbysundell.com/posts/the-power-of-key-paths-in-swift , podemos declarar una herramienta más poderosa que puede filtrar la unicidad en cualquier keyPath. Gracias a los comentarios de Alexander sobre varias respuestas con respecto a la complejidad, las siguientes soluciones deberían ser casi óptimas.
Solución no mutante
Extendemos con una función que puede filtrar por unicidad en cualquier keyPath:
extension RangeReplaceableCollection {
/// Returns a collection containing, in order, the first instances of
/// elements of the sequence that compare equally for the keyPath.
func unique<T: Hashable>(for keyPath: KeyPath<Element, T>) -> Self {
var unique = Set<T>()
return filter { unique.insert($0[keyPath: keyPath]).inserted }
}
}
Nota: en el caso de que su objeto no se ajuste a RangeReplaceableCollection, pero sí a Sequence, puede tener esta extensión adicional, pero el tipo de retorno siempre será un Array:
extension Sequence {
/// Returns an array containing, in order, the first instances of
/// elements of the sequence that compare equally for the keyPath.
func unique<T: Hashable>(for keyPath: KeyPath<Element, T>) -> [Element] {
var unique = Set<T>()
return filter { unique.insert($0[keyPath: keyPath]).inserted }
}
}
Uso
Si queremos unicidad para los elementos mismos, como en la pregunta, usamos keyPath
/.self
.self:
let a = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let b = a.unique(for: /.self)
/* b is [1, 4, 2, 6, 24, 15, 60] */
Si queremos unicidad para otra cosa (como la
id
de una colección de objetos), usamos el keyPath de nuestra elección:
let a = [CGPoint(x: 1, y: 1), CGPoint(x: 2, y: 1), CGPoint(x: 1, y: 2)]
let b = a.unique(for: /.y)
/* b is [{x 1 y 1}, {x 1 y 2}] */
Solución de mutación
Extendemos con una función de mutación que puede filtrar por unicidad en cualquier keyPath:
extension RangeReplaceableCollection {
/// Keeps only, in order, the first instances of
/// elements of the collection that compare equally for the keyPath.
mutating func uniqueInPlace<T: Hashable>(for keyPath: KeyPath<Element, T>) {
var unique = Set<T>()
removeAll { !unique.insert($0[keyPath: keyPath]).inserted }
}
}
Uso
Si queremos unicidad para los elementos mismos, como en la pregunta, usamos keyPath
/.self
.self:
var a = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
a.uniqueInPlace(for: /.self)
/* a is [1, 4, 2, 6, 24, 15, 60] */
Si queremos unicidad para otra cosa (como la
id
de una colección de objetos), usamos el keyPath de nuestra elección:
var a = [CGPoint(x: 1, y: 1), CGPoint(x: 2, y: 1), CGPoint(x: 1, y: 2)]
a.uniqueInPlace(for: /.y)
/* a is [{x 1 y 1}, {x 1 y 2}] */
Muchas respuestas disponibles aquí, pero me perdí esta extensión simple, adecuada para Swift 2 y versiones posteriores:
extension Array where Element:Equatable {
func removeDuplicates() -> [Element] {
var result = [Element]()
for value in self {
if result.contains(value) == false {
result.append(value)
}
}
return result
}
}
Lo hace super simple. Se puede llamar así:
let arrayOfInts = [2, 2, 4, 4]
print(arrayOfInts.removeDuplicates()) // Prints: [2, 4]
Filtrado basado en propiedades
Para filtrar una matriz basada en propiedades, puede usar este método:
extension Array {
func filterDuplicates(@noescape includeElement: (lhs:Element, rhs:Element) -> Bool) -> [Element]{
var results = [Element]()
forEach { (element) in
let existingElements = results.filter {
return includeElement(lhs: element, rhs: $0)
}
if existingElements.count == 0 {
results.append(element)
}
}
return results
}
}
A lo que puede llamar de la siguiente manera:
let filteredElements = myElements.filterDuplicates { $0.PropertyOne == $1.PropertyOne && $0.PropertyTwo == $1.PropertyTwo }
Para las matrices donde los elementos no son Hashable ni Comparable (por ejemplo, objetos complejos, diccionarios o estructuras), esta extensión proporciona una forma generalizada de eliminar duplicados:
extension Array
{
func filterDuplicate<T:Hashable>(_ keyValue:(Element)->T) -> [Element]
{
var uniqueKeys = Set<T>()
return filter{uniqueKeys.insert(keyValue($0)).inserted}
}
func filterDuplicate<T>(_ keyValue:(Element)->T) -> [Element]
{
return filterDuplicate{"/(keyValue($0))"}
}
}
// example usage: (for a unique combination of attributes):
peopleArray = peopleArray.filterDuplicate{ ($0.name, $0.age, $0.sex) }
or...
peopleArray = peopleArray.filterDuplicate{ "/(($0.name, $0.age, $0.sex))" }
No tiene que molestarse en hacer valores Hashable y le permite usar diferentes combinaciones de campos para la unicidad.
Nota: para un enfoque más sólido, consulte la solución propuesta por Coeur en los comentarios a continuación.
[EDITAR] alternativa a Swift 4
Con Swift 4.2 puedes usar la clase Hasher para construir un hash mucho más fácil. La extensión anterior se puede cambiar para aprovechar esto:
extension Array
{
func filterDuplicate(_ keyValue:((AnyHashable...)->AnyHashable,Element)->AnyHashable) -> [Element]
{
func makeHash(_ params:AnyHashable ...) -> AnyHashable
{
var hash = Hasher()
params.forEach{ hash.combine($0) }
return hash.finalize()
}
var uniqueKeys = Set<AnyHashable>()
return filter{uniqueKeys.insert(keyValue(makeHash,$0)).inserted}
}
}
La sintaxis de la llamada es un poco diferente porque el cierre recibe un parámetro adicional que contiene una función para codificar un número variable de valores (que debe ser Hashable individualmente)
peopleArray = peopleArray.filterDuplicate{ $0($1.name, $1.age, $1.sex) }
También funcionará con un único valor de unicidad (usando $ 1 e ignorando $ 0).
peopleArray = peopleArray.filterDuplicate{ $1.name }
Puede convertir a un conjunto y volver a una matriz nuevamente con bastante facilidad:
let unique = Array(Set(originals))
Esto no garantiza mantener el orden original de la matriz.
Puede rodar el suyo, por ejemplo, de esta manera ( actualizado para Swift 1.2 con Set ):
func uniq<S : SequenceType, T : Hashable where S.Generator.Element == T>(source: S) -> [T] {
var buffer = [T]()
var added = Set<T>()
for elem in source {
if !added.contains(elem) {
buffer.append(elem)
added.insert(elem)
}
}
return buffer
}
let vals = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let uniqueVals = uniq(vals) // [1, 4, 2, 6, 24, 15, 60]
Versión Swift 3:
func uniq<S : Sequence, T : Hashable>(source: S) -> [T] where S.Iterator.Element == T {
var buffer = [T]()
var added = Set<T>()
for elem in source {
if !added.contains(elem) {
buffer.append(elem)
added.insert(elem)
}
}
return buffer
}
Y como una extensión para
Array
:
extension Array where Element: Hashable {
var uniques: Array {
var buffer = Array()
var added = Set<Element>()
for elem in self {
if !added.contains(elem) {
buffer.append(elem)
added.insert(elem)
}
}
return buffer
}
}
Puede usar directamente una colección de conjuntos para eliminar duplicados y luego volver a convertirlos en una matriz
var myArray = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
var mySet = Set<Int>(myArray)
myArray = Array(mySet) // [2, 4, 60, 6, 15, 24, 1]
Entonces puedes ordenar tu matriz como quieras
myArray.sort{$0 < $1} // [1, 2, 4, 6, 15, 24, 60]
Swift 3.0
let uniqueUnordered = Array(Set(array))
let uniqueOrdered = Array(NSOrderedSet(array: array))
Swift 4
public extension Array where Element: Hashable {
func uniqued() -> [Element] {
var seen = Set<Element>()
return filter{ seen.insert($0).inserted }
}
}
cada intento de
insert
también devolverá una tupla:
(inserted: Bool, memberAfterInsert: Set.Element)
.
Ver
documentation
.
El uso del valor devuelto nos ayuda a evitar bucles o realizar cualquier otra operación.
Swift 4.x:
extension Sequence where Iterator.Element: Hashable {
func unique() -> [Iterator.Element] {
return Array(Set<Iterator.Element>(self))
}
func uniqueOrdered() -> [Iterator.Element] {
return reduce([Iterator.Element]()) { $0.contains($1) ? $0 : $0 + [$1] }
}
}
uso:
["Ljubljana", "London", "Los Angeles", "Ljubljana"].unique()
o
["Ljubljana", "London", "Los Angeles", "Ljubljana"].uniqueOrdered()
Una solución alternativa (si no óptima) desde here usando tipos inmutables en lugar de variables:
func deleteDuplicates<S: ExtensibleCollectionType where S.Generator.Element: Equatable>(seq:S)-> S {
let s = reduce(seq, S()){
ac, x in contains(ac,x) ? ac : ac + [x]
}
return s
}
Incluido para contrastar el enfoque imperativo de Jean-Pillippe con un enfoque funcional.
Como beneficio adicional, esta función funciona tanto con cadenas como con matrices.
Editar:
esta respuesta se escribió en 2014 para Swift 1.0 (antes de que
Set
estuviera disponible en Swift).
No requiere conformidad Hashable y se ejecuta en tiempo cuadrático.
Una solución más de Swift 3.0 para eliminar duplicados de una matriz. Esta solución mejora en muchas otras soluciones ya propuestas por:
- Preservar el orden de los elementos en la matriz de entrada
- Complejidad lineal O (n): filtro de paso único O (n) + inserción de conjunto O (1)
Dada la matriz de enteros:
let numberArray = [10, 1, 2, 3, 2, 1, 15, 4, 5, 6, 7, 3, 2, 12, 2, 5, 5, 6, 10, 7, 8, 3, 3, 45, 5, 15, 6, 7, 8, 7]
Código funcional:
func orderedSet<T: Hashable>(array: Array<T>) -> Array<T> {
var unique = Set<T>()
return array.filter { element in
return unique.insert(element).inserted
}
}
orderedSet(array: numberArray) // [10, 1, 2, 3, 15, 4, 5, 6, 7, 12, 8, 45]
Código de extensión de matriz:
extension Array where Element:Hashable {
var orderedSet: Array {
var unique = Set<Element>()
return filter { element in
return unique.insert(element).inserted
}
}
}
numberArray.orderedSet // [10, 1, 2, 3, 15, 4, 5, 6, 7, 12, 8, 45]
Este código aprovecha el resultado devuelto por la operación de
insert
en
Set
, que se ejecuta en
O(1)
, y devuelve una tupla que indica si el elemento se insertó o si ya existía en el conjunto.
Si el elemento estaba en el conjunto, el
filter
lo excluirá del resultado final.
Versión de sintaxis un poco más sucinta de la respuesta Swift 2 de Daniel Krom , usando un cierre final y un nombre de argumento abreviado, que parece estar basado en la respuesta original de Airspeed Velocity :
func uniq<S: SequenceType, E: Hashable where E == S.Generator.Element>(source: S) -> [E] {
var seen = [E: Bool]()
return source.filter { seen.updateValue(true, forKey: $0) == nil }
}
Ejemplo de implementación de un tipo personalizado que se puede usar con
uniq(_:)
(que debe cumplir con
Hashable
y, por lo
Equatable
,
Equatable
, porque
Hashable
extiende con
Equatable
):
func ==(lhs: SomeCustomType, rhs: SomeCustomType) -> Bool {
return lhs.id == rhs.id // && lhs.someOtherEquatableProperty == rhs.someOtherEquatableProperty
}
struct SomeCustomType {
let id: Int
// ...
}
extension SomeCustomType: Hashable {
var hashValue: Int {
return id
}
}
En el código anterior ...
id
, como se usa en la sobrecarga de
==
, podría ser cualquier tipo
Equatable
(o método que devuelva un tipo
Equatable
, por ejemplo,
someMethodThatReturnsAnEquatableType()
).
El código comentado demuestra que se extiende la verificación de igualdad, donde
someOtherEquatableProperty
es otra propiedad de un tipo
Equatable
(pero también podría ser un método que devuelve un tipo
Equatable
).
id
, como se usa en la propiedad calculada
hashValue
(requerida para cumplir con
Hashable
), podría ser cualquier
Hashable
(y por lo tanto
Equatable
) (o método que devuelve un tipo
Hashable
).
Ejemplo de uso de
uniq(_:)
:
var someCustomTypes = [SomeCustomType(id: 1), SomeCustomType(id: 2), SomeCustomType(id: 3), SomeCustomType(id: 1)]
print(someCustomTypes.count) // 4
someCustomTypes = uniq(someCustomTypes)
print(someCustomTypes.count) // 3
editar / actualizar Swift 4 o posterior
También podemos ampliar el protocolo
RangeReplaceableCollection
para permitir que se use también con los tipos
StringProtocol
:
extension RangeReplaceableCollection where Element: Hashable {
var orderedSet: Self {
var set = Set<Element>()
return filter { set.insert($0).inserted }
}
mutating func removeDuplicates() {
var set = Set<Element>()
removeAll { !set.insert($0).inserted }
}
}
let integers = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let integersOrderedSet = integers.orderedSet // [1, 4, 2, 6, 24, 15, 60]
"abcdefabcghi".orderedSet // "abcdefghi"
"abcdefabcghi".dropFirst(3).orderedSet // "defabcghi"
Método de mutación:
var string = "abcdefabcghi"
string.removeDuplicates()
string // "abcdefghi"
var substring = "abcdefabcdefghi".dropFirst(3) // "defabcdefghi"
substring.removeDuplicates()
substring // "defabcghi"
Para Swift 3 haga clic here
Swift 4
Garantizado para seguir ordenando.
extension Array where Element: Equatable {
func removingDuplicates() -> Array {
return reduce(into: []) { result, element in
if !result.contains(element) {
result.append(element)
}
}
}
}
func removeDublicate (ab: [Int]) -> [Int] {
var answer1:[Int] = []
for i in ab {
if !answer1.contains(i) {
answer1.append(i)
}}
return answer1
}
Uso:
let f = removeDublicate(ab: [1,2,2])
print(f)