web-dev-qa-db-ja.com

カスタムオブジェクトの配列から重複を削除するSwift

次のように定義されたカスタムクラスがあります。

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

これで配列_myChats = [DisplayMessage]?_ができました。 idフィールドは、DisplayMessageオブジェクトごとに一意です。配列を確認して重複をすべて削除する必要があります。基本的に、配列内のすべてのオブジェクトが一意のidを持っていることを確認してください。 NSMutableArrayEquatableを使用したいくつかの解決策を見てきましたが、ここでそれらをどのように適応させるかわかりません。私はArray(Set(myChats))も知っていますが、カスタムオブジェクトの配列では機能しないようです。

15
Alk

次のように、一連の文字列でそれを行うことができます。

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

これまでに見たすべてのIDのセットを保持し、ループ内のすべてのアイテムを調べ、まだ見たことのないIDを追加するという考え方です。

13
dasblinkenlight

以下は、指定されたキーに基づいてオブジェクトの一意のリストを返す配列拡張です。

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
    }
}

あなたの例のために:

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

指定されたキーに基づく等価比較を使用して、配列の無料の複製バージョンを作成します

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

}

使用方法

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)
3

以下は、Arrayに基づいてオブジェクトの一意のリストを返すkeyPath拡張機能です。

extension Array {

    func uniques<T: Hashable>(by keyPath: KeyPath<Element, T>) -> [Element] {
        return reduce([]) { result, element in
            let alreadyExists = (result.contains(where: { $0[keyPath: keyPath] == element[keyPath: keyPath] }))
            return alreadyExists ? result : result + [element]
        }
    }
}

使用法:

myChats.uniques(by: \.id)
0
nightwill