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.
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.
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 ?? ""}
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)