2016-03-22 11 views
0

このコードは、文字列配列を最初の文字でグループ化するために使用します。2つのループを1つに結合する

//plain array 
var list = ["apple", "apricot", "banana", "blackberry"] 

//dictionary of arrays 
var dict = Dictionary<String, Array<String>>() 

//create necessary keys from first characters 
for word in list { 
    dict[ String(word.characters.prefix(1)) ] = [ ] 
} 

//add words to the key of their first character 
for word in list { 
    dict[ String(word.characters.prefix(1)) ]?.append(word) 
} 

//output dictionary 
print(dict) 

この例では、出力は、このような辞書であろう:

[ "b": ["ba", "bb"], 
    "a": ["aa", "ab"] ] 

コードは、2つの類似forループを有しています。出力に影響を与える単一のループに結合することはできますか? groupBy機能のための完璧な仕事のような

答えて

3

サウンド:

extension Array { 
    func groupBy<T: Hashable>(f: Element -> T) -> [T: [Element]] { 
     var results = [T: [Element]]() 
     for element in self { 
      let key = f(element) 
      if results[key] != nil { 
       results[key]!.append(element) 
      } else { 
       results[key] = [element] 
      } 
     } 
     return results 
    } 
} 

var list = ["apple", "apricot", "banana", "blackberry"] 
let dict = list.groupBy { 
    String($0.characters.prefix(1)) 
} 

のは、ステップバイステップでそれを見てみましょう:

  • groupByは、各要素の配列にキーを与える関数をとります。これは、キーと同じキーを持つ要素のリストを含む辞書を返します。
  • fは、キー付与機能です。配列の各要素について、結果ディクショナリにすでにそのキーがあるかどうかを確認します。はいの場合、そのキーの要素のリストに追加されます。いいえの場合、そのキーの新しい配列を作成します。
+0

これは意味があります。私は 'groupBy'を考えなかった。したがって、関数は要素を追加する前にキーがすでに作成されているかどうかを確認するだけです。 –

+0

キーの順序を保持することは可能ですか? –

+1

辞書には順序がありません。キーのリストを取得し、それらをソートし、その順序で辞書を繰り返します。 –

1
//plain array 
    let list = ["apple", "apricot", "banana", "blackberry"] 

    //dictionary of arrays 
    var dict = Dictionary<String, Array<String>>() 

    //create necessary keys from first characters 
    for word in list { 

     if let _ = dict[ String(word.characters.prefix(1))] { 
      dict[ String(word.characters.prefix(1))]?.append(word) 
     } 
     else{ 
      dict[ String(word.characters.prefix(1)) ] = [word] 
     } 
    } 

    //output dictionary 
    print(dict)