如何基于属性Swift将2个自定义对象数组添加到一个唯一数组中

时间:2017-11-09 12:05:34

标签: ios arrays swift class unique

我们假设我有一个类似于此的自定义类

class Person: NSObject {

    let name: String
    let id: Int


    init(name: String, id: Int) {
        self.name = name
        self.id = id
    }
}

我有2个对象数组

        let p1 = Person(name: "as", id: 1)
        let p2 = Person(name: "sa", id: 100)
        let p3 = Person(name: "fa", id: 8)
        let p4 = Person(name: "wq", id: 5)
        let p5 = Person(name: "wqq", id: 123)

        let p10 = Person(name: "sad", id: 8)
        let p11 = Person(name: "cxz", id: 12)
        let p12 = Person(name: "vcx", id: 11)
        let p13 = Person(name: "xc", id: 1)

        let arrPerson = [p1, p2, p3, p4, p5]
        let arrPersonB = [p10, p11, p12, p13]

我需要根据它们的id将这两个数组添加到一个唯一的对象数组中。因此,唯一数组应包含[p2, p4, p5, p11, p12]

4 个答案:

答案 0 :(得分:0)

我们的想法是计算每个id的出现次数,如果计数为1,则只计算Person

let allPersons = arrPerson + arrPersonB
var occurences: [Int: Int] = [:]
allPersons.forEach { occurences[$0.id, default: 0] += 1}
//[12: 1, 11: 1, 123: 1, 100: 1, 5: 1, 1: 2, 8: 2]
let uniquePersons = occurences
    .filter({ $0.value == 1 })
    .map({ id -> Person in
        allPersons.first(where: { $0.id == id.key })!
    })
print(uniquePersons.map { $0.id }) //[12, 100, 123, 5, 11]

答案 1 :(得分:0)

有很多方法可以做到这一点。这是使用NSCountedSet

的人
let idSet = NSCountedSet(array: (arrPersonA + arrPersonB).map { $0.id })
let arr = (arrPersonA + arrPersonB).filter { idSet.count(for: $0.id) == 1 }
  • NSCountedSet包含所有id的列表及其出现次数
  • 对于仅在集合
  • 中出现一次的项目的第二行过滤器

答案 2 :(得分:0)

这是一种使用自定义匹配函数使序列唯一的灵活方法。

请注意,您需要对其进行调整,以便控制您希望保留哪个对象。

extension Sequence where Iterator.Element: Hashable {

    func unique(matching: (Iterator.Element, Iterator.Element) -> Bool) -> [Iterator.Element] {

        var uniqueArray: [Iterator.Element] = []
        forEach { element in
            let isUnique = uniqueArray.reduce(true, { (result, item) -> Bool in
                return result && matching(element, item)
            })
            if isUnique {
                uniqueArray.append(element)
            }
        }
        return uniqueArray
    }
}

在你的情况下,电话会是

let uniqueArray = (arrPerson+arrPersonB).unique { $0.id != $1.id }
print(uniqueArray.map { $0.id }) // [1, 100, 8, 5, 123, 12, 11]

答案 3 :(得分:-2)

您可以使用.filter根据您喜欢的条件仅选择您想要的元素

例如:

let ids = [4, 5, 6, 7] // list of the IDs you want to select

var finalPersons = arrPerson // we copy the first array
finalPersons.append(contentsOf: arrPersonB) // we append the content of the second
finalPersons = finalPersons.filter{ ids.contains($0.id) } // finally we filter to retain only those Persons who corresponds