Вычитание двух массивов объектов, основанных на свойствах объектов

47
6

Скажем, у меня есть 2 массива экземпляров класса "Человек". У класса Person есть свойства "имя", "возраст", "id". "id" - уникальный идентификатор, поэтому его можно использовать для сравнения людей. Итак, скажем, у меня есть два массива людей:

[ {Name: Bob,Age: 18,ID: 142353}, {Name: Rob, Age: 40,ID: 142350}, {Name: Andy, Age: 30,ID: 142359}, {Name: Andy, Age: 21,ID: 142340}  ]

[ {Name: Jack,Age: 18,ID: 142362}, {Name: James, Age: 40,ID: 142311}, {Name: Rob, Age: 40,ID: 142350}, {Name: Andy, Age: 21,ID: 142340} ]

Я хочу сравнить идентификаторы людей и получить те, которые отличаются от массива 1 от массива в массиве 2, поэтому результат должен выглядеть так:

[{Name: Bob,Age: 18,ID: 142353}, {Name: Andy, Age: 30,ID: 142359}]

То, как я делаю это сейчас в Свифте:

   let new = newPeople.filter({ p1 in
previousPeople.contains(where: { p2 in
p1.id != p2.id
})
})

Но я не думаю, что это работает. Не могу понять, что не так с моей реализацией.

спросил(а) 2016-12-15T14:57:00+03:00 2 года, 11 месяцев назад
2
Решение
64

Вы хотите, чтобы ваш класс Person соответствовал Equatable протоколу.

extension Person: Equatable {
static func ==(lhs: Person, rhs: Person) -> Bool {
return lhs.id == rhs.id
}
}

то вы можете сделать простой фильтр двух массивов:

let person1 = Person(name: "J", age: 20, id: UUID())
let person2 = Person(name: "K", age: 40, id: UUID())
let person3 = Person(name: "L", age: 30, id: UUID())
let person4 = Person(name: "M", age: 25, id: UUID())
let person5 = Person(name: "N", age: 39, id: UUID())

let personArray1 = [person1, person2, person3]
let personArray2 = [person4, person2, person3]

let filteredPersonArray = personArray1.filter { !personArray2.contains($0) }
//filteredPersonArray.count == 1 which is person4

ответил(а) 2016-12-15T15:17:00+03:00 2 года, 11 месяцев назад
Еще 1 ответ
44

Создайте Set идентификаторов, которые вы не хотите сохранять, и отфильтруйте своих людей, проверив, contains против этого Set. Вы можете получить Array идентификаторов из Array людей, используя people.map{ $0.id }.

struct Person {
let name: String
let age: Int
let id: Int
}

let people1 = [
Person(name: "Bob", age: 18, id: 142353),
Person(name: "Rob", age: 40, id: 142350),
Person(name: "Andy", age: 30, id: 142359),
Person(name: "Andy", age: 21, id: 142340)
]

let people2 = [
Person(name: "Jack", age: 18, id: 142362),
Person(name: "James", age: 40, id: 142311),
Person(name: "Rob", age: 40, id: 142350),
Person(name: "Andy", age: 21, id: 142340)
]

let undesiredIDs = Set(people2.map{ $0.id })
print("Keeping all people that don't have one of these IDs: \(undesiredIDs)\r\n\r\n")

let filteredPeople = people1.filter{ !undesiredIDs.contains($0.id) }

print("Original list: \(people1).\r\n\r\n")
print("Filtered: \(filteredPeople)")

ответил(а) 2016-12-15T19:19:00+03:00 2 года, 11 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема