清除通过唯一字典值过滤字典数组的方法

Aar*_*ron 3 arrays dictionary filter swift

说我有一个对象:

struct Foo {
    let id: Int
    let bar: Int
}
Run Code Online (Sandbox Code Playgroud)

现在我在数组中有5个这样的对象:

let foo1 = Foo(id: 1, bar: 1)
let foo2 = Foo(id: 2, bar: 1)
let foo3 = Foo(id: 3, bar: 2)
let foo4 = Foo(id: 4, bar: 3)
let foo5 = Foo(id: 5, bar: 3)

let fooArray = [foo1, foo2, foo3, foo4, foo5] 
Run Code Online (Sandbox Code Playgroud)

过滤foo具有唯一bar值的对象的干净方法是什么?

// Desired output
let filteredArray = [foo1, foo3, foo4]
Run Code Online (Sandbox Code Playgroud)

假设有几百到几千个对象可以迭代.

Mar*_*n R 5

一种可能的方法是使用a Set来跟踪 bar已经看到的值:

var seenBarValues = Set<Int>()
let filteredArray = fooArray.filter { foo in
    if seenBarValues.contains(foo.bar) {
        // We already had a `Foo` with this `bar` value: skip.
        return false 
    } else {
        // First `Foo` with this `bar` value: remember and include.
        seenBarValues.insert(foo.bar)
        return true
    }
}
Run Code Online (Sandbox Code Playgroud)

正如@Hamish正确指出的那样,这可以缩短为

var seenBarValues = Set<Int>()
let filteredArray = fooArray.filter { 
    seenBarValues.insert($0.bar).inserted
}
Run Code Online (Sandbox Code Playgroud)

用这个事实

public mutating func insert(_ newMember: Element) -> (inserted: Bool, memberAfterInsert: Element)
Run Code Online (Sandbox Code Playgroud)

返回一个元组,其第一个成员指示一个元素是否等于新插入的元素是否已存在于该集合中.

  • 或者你可以说`fooArray.filter {seenBarValues.insert($ 0.bar).inserted}`:) (2认同)