コレクションのトランスフォームオペレーション
Kotlinの標準ライブラリは、コレクションの トランスフォーム(変形) のための拡張関数を幾つか提供しています。 これらの関数は、既存のコレクションから指定されたルールに従い変形した新しいコレクションを作り出します。 このページでは、提供されているコレクションの変形関数の概要を提示します。
Map
(訳注:コレクションのマップとは別なので注意)
マッピングトランスフォームはあるコレクションの要素に対して関数を適用した結果をもとに新しいコレクションを作り出すものです。
基本的なマッピング関数としては、map()
が挙げられます。
これは渡されたラムダ関数を個々の要素に適用して、その結果のリストを返します。
結果の順番は元の要素の順番と同じです。
要素の他に要素のインデックスも使う変形を行いたければ、mapIndexed()
を使います。
もし変形がある種の要素に対してnull
を生成する場合、map()
関数の代わりにmapNotNull()
関数を使う事で、
null
を結果のコレクションから除外する事が出来ます。
mapIndexed()
の代わりにも同様にmapIndexedNotNull()
があります。
(コレクションの)マップをトランスフォームする場合は、2つの選択肢があります:
値を変更せずにキーだけをトランスフォームするか、逆にキーを変更せずに値だけをトランスフォームするかです。
キーをトランスフォームしたい場合は mapKeys()
を使います。
値をトランスフォームしたい場合はmapValues()
を使います。
どちらの関数もトランスフォーム関数にはマップのエントリが引数としてやってくるので、キーと値の両方を使って変換を行う事が出来ます。
Zip
zipトランスフォーメーションは2つのコレクションの同じ位置にある要素から、それらのペアを持ったコレクションを作り出します。
Kotlinの標準ライブラリでは、これはzip()
拡張関数で行う事が出来ます。
コレクションか配列に対してコレクション(か配列)を引数として指定すると、
zip()
はPair
オブジェクトのList
を返します。(訳注:わかりにくいので後の例を見ると良い)
レシーバのコレクションの要素が、各ペアの最初の方の要素となります。
2つのコレクションのサイズが異なる場合、zip()
の結果は小さい方のサイズとして生成されます。
長い方の残りの要素は結果には含まれません。
zip()
関数は中置型(infix)でa zip b
の形式で使う事も出来ます。
zip()
に2つのパラメータを持つトランスフォーメーション関数をさらに渡す事も出来ます:
2つのパラメータはレシーバの要素と引数の要素です。
この場合、結果のList
は、それぞれ同じ位置のレシーバの要素と引数の要素のペアに対して呼ばれた変形関数の結果から作られるList
となります。
Pair
のList
がある場合に、逆の変換、unzipする事が出来ます。
つまり、ペアのリストから、2つのバラしたリストを作る訳です:
- 最初のリストは各
Pair
の1つ目の要素からなるリスト - 二番目のリストはペアの2つ目の要素からなるリスト
ペアのリストをunzipするためには、unzip()
関数を呼びます:
Associate
Association(連想、関連付け)トランスフォーメーションはコレクションの要素から、それに関連づけした値を持つマップを作る。 associationの種類によって、要素は結果のマップのキーの方にも値の方にもなります。
基本的なassociation関数、 associateWith()
は、
元のコレクションの要素がキーで、提供されるトランスフォーム関数で生成される結果が値となるMap
を作りだします。
2つの等しい要素がある場合は、後に来た方だけが結果のマップに残ります。
コレクションの要素を結果のマップの値の方にするものとしては、
associateBy()
関数があります。
associateBy()
は引数に、要素の値を元にキーを返す関数を取ります。
もし2つの要素に対応するキーの値が等しい場合は、後に来た方だけが結果のマップに残ります。
associateBy()
はvalueの方を変換する関数(valueTransform)をつけて呼ぶ事も出来ます。
キーと値の両方を渡された関数が生成するようなマップの生成方法としては、
associate()
関数があります。
associate()
はPair
を返す関数を引数に取ります。このペアがキーと値として結果のマップのエントリになります。
associate()
は短寿命のPair
オブジェクトを生成するので、パフォーマンスに影響があるかもしれない事に注意しましょう。
だからassociate()
の使用はパフォーマンスが問題にならないか、他の選択肢よりこちらの方が良い場合に限って使うようにしましょう。
後者の例としては、元の要素からキーと値の両方が一緒に作り出されるような場合です。
ここでは要素に変形をする関数をまず適用して、その結果のプロパティからペアを作っています。
Flatten
ネストしたコレクションを操作している時には、ネストしたコレクションの要素に対するフラットなアクセスを提供する標準ライブラリを便利に使える事があるでしょう。
そのような関数の最初のものは、flatten()
です。
この関数はコレクションのコレクション、例えばSet
のList
などに呼ぶ事が出来ます。
この関数は、ネストしたコレクションに含まれた全要素を含む単独のList
を返します。
他の関数としてはflatMap()
があります。
これはネストしたコレクションを処理する柔軟な方法を提供します。
flatMap()
はコレクション要素を別のコレクションに変換する関数を引数に取ります。
結果としてはflatMap()
は単一のリストで、その要素は返された全要素を含むものとなります。
つまりflatMap()
はmap()
関数(コレクションをコレクションに変換する)を実行したあとに、その結果にflatten()
を適用する、
というように続けて2つを呼び出したかのように振る舞います。
文字列表現
もしコレクションの内容を人間に読めるようなフォーマットで取り出したいと思うなら、
コレクションを文字列に変形するような関数を使うのが良いでしょう:
joinToString()
と
joinTo()
の出番です。
joinToString()
は渡された引数を元にコレクションの要素達から一つのString
を組み立てます。
joinTo()
は同じ事を、渡されたAppendable
オブジェクトに結果を追加してく事で行います。
デフォルトの引数で呼ぶと、この関数はコレクションのtoString()
を呼んだのと似たような結果を返します:
要素の文字列表現をカンマとスペースで区切ったString
です。
カスタムな文字列表現を作りたければ、関数の引数でseparator
, prefix
, postfix
を指定する事が出来ます。
結果の文字列はprefix
で始まり、postfix
で終わります。
separator
は最後の要素を除いた各要素のあとに来ます。
より大きなコレクションに対しては、limit
を指定したいと思うかもしれません。
これは、結果に含める総数の上限です。
もしコレクションのサイズがlimit
を超えたら、それ以後のすべての要素の代わりにtruncated
引数で指定された値一つに置き換わる事になります。
最後に、要素自身の表現をカスタマイズしたければ、
transform
関数を渡す事が出来ます。