Reputation: 2809
I have an array of model objects that I have created from JSON data. I have thousands of records that contain duplicates, which I need to remove. A record is considered a duplicate if it has the same "name", and the same "address" attributes.
The problem is, the only way I know how to remove the duplicate objects is by performing a for loop, within a for loop search, and I'm wondering if there is not a better, more efficient way? I figure that the best approach for this would be to use the "filter" method, but I'm having difficulty configuring it to work with an array that contains model objects with multiple attributes.
My model object looks like this:
struct Person {
let id: Int
let name: String
let address: String
init(id:Int, name:String, address:String) {
self.id = id
self.name = name
self.address = address
}
}
The way I'm trying to use the filter method on my array of model objects looks like this (which I know does not work):
let uniqueArray = peopleArray.filter { $0.name == $1.name, $0.address == $1.address }
Can anyone see what it is I'm doing wrong?
Upvotes: 1
Views: 807
Reputation: 38833
1: You need to make your struct conform to Equatable protocol
func ==(lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name && lhs.address == rhs.address
}
2: You can use a set to control which objects to filter from your array but you will need to make your struct conform to Hashable protocol adding a hashValue property to it.
struct Person: Equatable, Hashable {
let id: Int
let name: String
let address: String
init(id: Int, name: String, address: String) {
self.id = id
self.name = name
self.address = address
}
var hashValue: Int {
return name.hashValue ^ address.hashValue
}
}
3: Usage
let people = [Person(id: 1, name: "Name A", address: "Address A"),
Person(id: 2, name: "Name B", address: "Address B"),
Person(id: 2, name: "Name B", address: "Address B"),
Person(id: 3, name: "Name C", address: "Address C")]
// Will keep the order
var set: Set<Person> = []
let orderedset = people.filter{ set.insert($0).inserted }
print(orderedset)
// Will not keep the order
let unique = Set<Person>(people)
print(unique)
Tip:
If the ID
is unique you should use it for comparison instead.
Upvotes: 7