2017-03-01 10 views
0

セイ値クリーンな方法は、私は、オブジェクトを持っている

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] 

繰り返し処理するオブジェクトが数百から数千になると仮定します。

+0

どのようにこのようにフィルタを使用する方法について: 'fooArray.filter {($ 0.bar.contains(検索バー))}' – rmp

+0

あなたの質問のタイトルと本文と異なるように見える - あなたは辞書の配列を持っていますか構造体の配列? – Hamish

+0

私は構造体の配列を持っていますが、この質問に対する答えは特に構造体型には当てはまりません。あなたが混乱していると感じたら、もっと意味的に適切なものにタイトルを自由に編集してください。私はより良いタイトルを考え出すことはできません。 – Aaron

答えて

3

一つの可能​​なアプローチ bar値がすでに見てきたかを追跡するSetを使用することです:

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) 

は、新たに挿入された要素にすでに という要素が存在するかどうかを示す最初の要素のタプルを返します。

+1

また、 'fooArray.filter {seenBarValues.insert($ 0.bar).inserted}')と言うこともできます。 – Hamish

+0

@Hamish:あなたは正しいです(いつものように)! –

+0

これは素晴らしいソリューションです。ありがとうございました – Aaron

関連する問題