要查找重复项,您可以按电话号码建立交叉引用,然后将其过滤为仅重复项。例如,考虑:
let contacts = [
Contact(name: "Rob", phone: "555-1111"),
Contact(name: "Richard", phone: "555-2222"),
Contact(name: "Rachel", phone: "555-1111"),
Contact(name: "Loren", phone: "555-2222"),
Contact(name: "Mary", phone: "555-3333"),
Contact(name: "Susie", phone: "555-2222")
]
在 Swift 4 中,您可以使用以下方法构建交叉引用字典:
let crossReference = Dictionary(grouping: contacts, by: { $0.phone })
或者,在 Swift 5.2 中(感谢SE-0249),您可以这样做:
let crossReference = Dictionary(grouping: contacts, by: \.phone)
或者
let crossReference = contacts.reduce(into: [String: [Contact]]()) {
$0[$1.phone, default: []].append($1)
}
然后,查找重复项:
let duplicates = crossReference
.filter { $1.count > 1 } // filter down to only those with multiple contacts
.sorted { $0.1.count > $1.1.count } // if you want, sort in descending order by number of duplicates
显然使用对您有意义的任何模型类型,但上面使用以下Contact 类型:
struct Contact {
let name: String
let phone: String
}
有很多很多的实现方式,所以我不会关注上面的实现细节,而是关注概念:通过某个键(例如电话号码)构建交叉引用原始数组,然后过滤结果只是那些具有重复值的键。
听起来您想将这种反映重复的结构展平为单个联系人数组(我不确定您为什么要这样做,因为您丢失了识别哪些是彼此重复的结构),但如果你想这样做,你可以flatMap它:
let flattenedDuplicates = crossReference
.filter { $1.count > 1 } // filter down to only those with multiple contacts
.flatMap { $0.1 } // flatten it down to just array of contacts that are duplicates of something else
对于 Swift 2 或 3 版本,请参阅 previous renditions of this answer。