Reputation: 6040
I have two custom struct-arrays...
struct CarStruct {
var name : String?
var speed : Int?
}
var allCarsArr = [CarStruct]() // should contain a lot of CarStructs
var newCarsArr = [CarStruct]() // contains only a few
I want to add the newCarsArr
to allCarsArr
.
But before that I need to prove that newCarsArr
does not contain structs which are already in allCarsArr
.
So how can I get all the structs
out of newCarsArr
which are not in allCarsArr
?
Upvotes: 1
Views: 1244
Reputation: 73186
As an alternative to working with sets (conforming CarStruct
to Hashable
), you could settle for conformance to Equatable
and simply check the allCarsArr
for duplicates of each car to be added from newCarsArr
.
/* (example of) conformance to Equatable */
func == (lhs: CarStruct, rhs: CarStruct) -> Bool {
return lhsName == rhsName && lhsSpeed == rhsSpeed
}
struct CarStruct : Equatable {
var name : String?
var speed : Int?
}
var allCarsArr = [CarStruct]()
var newCarsArr = [CarStruct]()
allCarsArr.append(CarStruct(name: "Volvo", speed: 42))
allCarsArr.append(CarStruct(name: "BMW", speed: 50))
newCarsArr.append(CarStruct(name: "BMW", speed: 80))
newCarsArr.append(CarStruct(name: "BMW", speed: 50)) // <-- duplicate
/* Add only cars from newCarsArr to allCarsArr if they don't
exist, priorly, in the latter */
newCarsArr.forEach { allCarsArr.contains($0) ? () : allCarsArr.append($0) }
If you work with large arrays, however, a better option for uniqueness is probably to use conformance to Hashable
and working with a set or dictionary (as the above will, if allCarsArr
grows very large, possibly yield an unwanted overhead), as is described in Kenneth Bruno:s solution above.
Upvotes: 2
Reputation:
You should add the Equatable
protocol as an extension to your class. This is an excellent article explaining it:
Every Value Type Should Be Equatable
Then you can add both arrays to a Set and it will naturally exclude duplicates. You also need to adhere to Hashable
in order to put the value in a Set but there's a simple trick of converting the value to a string and getting the hashValue
of that.
struct CarStruct {
var name : String?
var speed : Int?
}
extension CarStruct: Hashable, Equatable {
// For Hashable
var hashValue:Int { return "\(self.name),\(self.speed)".hashValue }
}
// For Equatable
func ==(lhs:CarStruct, rhs:CarStruct) -> Bool {
return lhs.name == rhs.name && lhs.speed == rhs.speed
}
var allCarsArr = [CarStruct]() // should contain a lot of CarStructs
let newCarsArr = [CarStruct]() // contains only a few
allCarsArr = Array(Set<CarStruct>(allCarsArr).union(newCarsArr))
Upvotes: 4