簡體   English   中英

清除通過唯一字典值過濾字典數組的方法

[英]Clean way to filter an array of dictionaries by unique dictionary values

說我有一個對象:

struct Foo {
    let id: Int
    let bar: Int
}

現在我在數組中有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] 

過濾具有唯一bar值的foo對象的干凈方法是什么?

// Desired output
let filteredArray = [foo1, foo3, foo4]

假設有幾百到幾千個對象可以迭代。

一種可能的方法是使用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
    }
}

正如@Hamish正確指出的那樣,這可以縮短為

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

用這個事實

public mutating func insert(_ newMember: Element) -> (inserted: Bool, memberAfterInsert: Element)

返回一個元組,其第一個成員指示一個元素是否等於新插入的元素是否已存在於該集合中。

我不是接受的答案的粉絲。 在閉包之外設置使用它似乎不合適。 我寧願把所有東西都包含在內。 有一個CS術語適用但我不記得它是什么...

我寧願看到這個:

let uniquedBars = fooArray
    .reduce(into: (result: [Foo](), set: Set<Int>())) { partial, next in
        if partial.set.insert(next.bar).inserted {
            partial.result.append(next)
        }
    }
    .result

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM