2017-02-16 3 views
0

データソースが[String:[User]という辞書の意味でコンタクトビューのように見えるテーブルビューをユーザーに表示しています]]だから私はセクション名をユーザー名の最初の文字で表示しています。オブジェクト配列内の特定のキーの型[String:[object]]のフィルタ辞書

ここで、ユーザーの名前で検索できるようにしたいのですが、これを動作させることはできません。

これらは辞書です...友人がこの["A" :[Users whose first name start with an A]]のようなデータを保持しますので、

var friends = [String: [User]]() 
var filteredFriends = [String: [User]]() 

にこれはsearchTextは私が

self.filteredFriends = self.friends.filter{friend in 
return friend.firstName.lowercased().contains(searchText)} 
で検索したい最初の名前であることと私のフィルタリングコードです

私がしたいのは、filteredFriendsのすべての値がfriendsで、ユーザーの最初の名前がテキストで始まるということです。

私のような辞書でこの作業を行うにはどうすればよいですか?

おかげ

詳細:

Class User { 
    var firstName: String? 

    init(name: String){ 
     self.firstName = name 
    } 
} 

サンプルシナリオ:

friends = ["A" : [User(name: "Anthony), User(name: "Arnold")], "B" : [User(name: "Barry")]] 
filteredFriends = friends 

searchText = "an" 

希望filteredFriends(最終結果)= ["A" : [User(name: "Anthony)]]

+0

サンプル入力し、所望の出力を提供してください。また、ユーザーの宣言を提供します。言い換えれば、私たちが必要なコードを構築するために必要なすべての情報を提供します。 – matt

+0

@matt question updated – Walker

+0

非常に良い、ありがとう。 – matt

答えて

1

簡単な方法はありません。あなたはこのように、全体の辞書を循環する必要があります。今

// these are your initial conditions 

class User { 
    let firstName: String 
    init(name: String) { 
     self.firstName = name 
    } 
} 
let friends : [String:[User]] = 
    ["A" : [User(name: "Anthony"), User(name: "Arnold")], 
    "B" : [User(name: "Barry")]] 
let searchText = "an" 

// and here we go... 

var filteredFriends = [String:[User]]() 
for entry in friends { 
    let filt = entry.value.filter{$0.firstName.lowercased().hasPrefix(searchText)} 
    if filt.count > 0 { 
     filteredFriends[entry.key] = filt 
    } 
} 

filteredFriendsは、所望の結果が含まれています。

+0

あなたはdictに 'enumerated()'を使ってキー/値を直接得ることができます – Alexander

+0

@Alexanderしかし、あなたはそうする必要はありません。私はタプル記法がより好きです。基本的に私たちのソリューションは、あなたのものがはるかに冗長であることを除いて、全く同じです(それは悪いことではありません:詳細はもっと明確になります)。 – matt

+0

うん、そうです。私は通常、適切な箇所にコメントの代わりにSOのかなり冗長な名前を書いています。彼らが望むなら、OPが彼らを変えるだろうと私は期待している。 – Alexander

1

mapを使用すると、各値(User配列)をフィルタリングして、入力辞書を出力辞書に変換することが理想的です。残念ながら、Dicationary.mapは新しい辞書ではなく[(Key, Value)]( `(Key、Value)タプルの配列)を返します。私はより慣習的で反復的なアプローチを取っていきます。

注:ファンクショナルスタイルを使用して周りに躍動感を抱かせる人は、reduceを使用することを約束しています。プロファイラを引き出し、減らして辞書を生成することがどれほど遅く、消費電力が高いかを見てみましょう。特にバッテリが限られているモバイル機器では重要です。ここで

は、私はそれを行うだろう方法は次のとおりです。

let allFriends = [String: [User]]() 
var filteredFriends = [String: [User]]() 

let searchText = "a".lowercased() 

for (initial, allFriendsWithInitial) in allFriends { 
    if initial.lowercased() == searchText { 
     // don't even have to bother filtering `friends` 
     filteredFriends[initial] = allFriendsWithInitial 
    } 

    let filteredFriendsWithInitial = allFriendsWithInitial.filter{ 
     $0.firstName.lowercased().contains(searchText) 
    } 

    if !filteredFriendsWithInitial.isEmpty { 
     filteredFriends[initial] = filteredFriendsWithInitial 
    } 
} 

print(filteredFriends) 
+0

@ハミッシュありがとう。あなたは私の目の中で信頼できるコミュニティメンバーです。将来のケースで私の回答を編集することは大歓迎です。 – Alexander

関連する問題