2016-03-27 1 views
1

У меня есть два пользовательских STRUCT-массивов ...Swift: HowTo получить разницу между двумя STRUCT-массивов

struct CarStruct { 
    var name : String? 
    var speed : Int? 
} 

var allCarsArr = [CarStruct]() // should contain a lot of CarStructs 
var newCarsArr = [CarStruct]() // contains only a few 

Я хочу, чтобы добавить newCarsArr к allCarsArr.

Но перед этим мне нужно доказать, что newCarsArr не содержит структур, которые уже находятся в allCarsArr.

Так как я могу получить все structs из newCarsArr, которых нет в allCarsArr?

ответ

4

Вы должны добавить протокол Equatable в качестве расширения вашего класса. Это отличная статья, объясняя это:

Every Value Type Should Be Equatable

Затем вы можете добавить оба массива в набор, и это, естественно, исключает дубликаты. Вы также должны придерживаться Hashable, чтобы поместить значение в набор, но есть простой способ преобразования значения в строку и получения hashValue.

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)) 
+0

Типы также должны соответствовать 'Hashable', которые должны быть разрешены в качестве членов' Set' (или ключей в словаре). (Соответствие самому 'Hashable' требует соответствия« Equatable »). – dfri

+0

Да, я просто работал над примером для публикации, когда сам это помнил. Благодаря! – ColGraff

+1

Обратите внимание, что просто используя свойство '.hashValue' простого представления' String 'свойств в структуре, хэш-значения могут не иметь очень хорошего распределения, увеличивая риск хэш-коллизий. Было бы целесообразно использовать, например, хеш-функции DJB, [как описано в ответе на этот вопрос и ответы) (http://codereview.stackexchange.com/questions/111545/implementing-the-hashable-protocol-in-swift-with-the-djb-hash- функция/111573 # 111573). – dfri

2

В качестве альтернативы работе с наборами (соответствующих CarStruct к Hashable), вы могли бы оседать на соответствие Equatable и просто проверить allCarsArr дубликатов каждого автомобиля, которые будут добавлены из 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) } 

Если вы работаете с большими массивами, однако, лучшим вариантом для уникальности, вероятно, использовать соответствие с Hashable и работать с набором или словарем (как выше воли, если allCarsArr растет очень большим, возможно, выход нежелательные служебные данные), как описано in Kenneth Bruno:s solution above.

Смежные вопросы