web-dev-qa-db-fra.com

Suppression de doublons d'un tableau d'objets personnalisés Swift

J'ai une classe personnalisée définie comme suit: 

class DisplayMessage : NSObject {
var id : String?
var partner_image : UIImage?
var partner_name : String?
var last_message : String?
var date : NSDate?
}

Maintenant, j'ai un tableau myChats = [DisplayMessage]?. Le champ id est unique pour chaque objet DisplayMessage. Je dois vérifier mon tableau et en supprimer tous les doublons, en veillant essentiellement à ce que tous les objets du tableau aient une id unique. J'ai vu des solutions utilisant NSMutableArray et Equatable mais je ne sais pas comment les adapter ici; Je connais aussi Array(Set(myChats)), mais cela ne semble pas fonctionner pour un tableau d'objets personnalisés.

9
Alk

Vous pouvez le faire avec un ensemble de chaînes, comme ceci:

var seen = Set<String>()
var unique = [DisplayMessage]
for message in messagesWithDuplicates {
    if !seen.contains(message.id!) {
        unique.append(message)
        seen.insert(message.id!)
    }
}

L'idée est de garder un ensemble de tous les identifiants que nous avons vus jusqu'à présent, de parcourir tous les éléments en boucle et d'ajouter ceux dont nous n'avons pas encore vu.

8
dasblinkenlight

Voici une extension Array pour renvoyer la liste unique d'objets basée sur une clé donnée:

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 arrayOrdered = [Element]() //keeping the unique list of elements but ordered
        for value in self {
            if !set.contains(map(value)) {
                set.insert(map(value))
                arrayOrdered.append(value)
            }
        }

        return arrayOrdered
    }
}

pour votre exemple, faites:

let uniqueMessages = messages.unique{$0.id ?? ""}
19
Ciprian Rarau

Créer une version gratuite en double d'un tableau, en utilisant des comparaisons d'égalité basées sur une clé donnée

public extension Sequence {

    public func uniq<Id: Hashable >(by getIdentifier: (Iterator.Element) -> Id) -> [Iterator.Element] {
        var ids = Set<Id>()
        return self.reduce([]) { uniqueElements, element in
            if ids.insert(getIdentifier(element)).inserted {
                return uniqueElements + CollectionOfOne(element)
            }
            return uniqueElements
        }
    }


   public func uniq<Id: Hashable >(by keyPath: KeyPath<Iterator.Element, Id>) -> [Iterator.Element] {
      return self.uniq(by: { $0[keyPath: keyPath] })
   }
}

public extension Sequence where Iterator.Element: Hashable {

    var uniq: [Iterator.Element] {
        return self.uniq(by: { (element) -> Iterator.Element in
            return element
        })
    }

}

Utilisation

let numbers =  [1,2,3,4,5,6,7,1,1,1,]
let cars = [Car(id:1), Car(id:1), Car(id:2)]

numbers.uniq
cars.uniq(by: { $0.id})
cars.uniq(by: \Car.id)
cars.uniq(by: \.id)
1