一种通过唯一词典值过滤词典数组的干净方法 [英] Clean way to filter an array of dictionaries by unique dictionary values

查看:65
本文介绍了一种通过唯一词典值过滤词典数组的干净方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个对象:

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

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

Now I have 5 of these objects in an array:

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对象的干净方法?

What would be a clean way of filtering foo objects that have unique bar values?

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

假设要迭代的对象从几百个到几千个.

Assume there's anywhere from a few hundred to a few thousand objects to iterate upon.

推荐答案

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

One possible approach is to use a Set which keeps track of which bar values have already been seen:

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正确指出的那样,可以将其缩短为

As @Hamish correctly pointed out, this can be shortened to

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

利用以下事实

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

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

returns a tuple whose first member indicates if an element equal to the newly inserted one was already present in the set.

这篇关于一种通过唯一词典值过滤词典数组的干净方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆