从自定义对象数组中删除重复项 Swift

25

我有一个自定义类的定义如下:

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)),但似乎不能用于自定义对象的数组。

请查看此链接:https://dev59.com/N1sW5IYBdhLWcg3wqo0x - Bista
4个回答

45

以下是一个数组扩展,根据给定的键返回唯一对象列表:

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

28
你可以使用一组字符串来完成它,就像这样:

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我们尚未见过的项目。


使用字典会更简单,不是吗? - Pascale Beaulac
那么这个解决方案的O(N)是多少? - Zhou Haibo
@ChuckZHB 这个解决方案的复杂度是O(N),其中N是“messagesWithDuplicates”集合中项目的数量,因为检查哈希集并将其插入哈希集的摊销成本为O(1)。 - Sergey Kalinichenko
太好了!我已经将这个解决方案添加到我的应用程序中。谢谢你。 - Zhou Haibo

17

这里有一个 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)

这是最好的答案 :) - luckyShubhra

10
创建一个免费的数组副本,使用基于给定键的相等比较。
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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接