KotlinのCollectionにある、groupBy
関数は、コレクションをMapにまとめることができますが、複数keyがあるときにやり方に迷ったので、メモしておきます。
と言ってもkeyは比較されるオブジェクトを指定できるので、equalsとかが適切に実装されていれば何でも良いです。
(パフォーマンスはわからないです)
準備
enum class Sex {Male, Female}
enum class Job {Engineer, Sales, Marketer}
data class Person(val name: String, val sex: Sex, val job : Job)
val persons = listOf(
Person("mike", Sex.Male, Job.Engineer),
Person("bob", Sex.Male, Job.Sales),
Person("sam", Sex.Male, Job.Marketer),
Person("lisa", Sex.Female, Job.Sales),
Person("alice", Sex.Female, Job.Engineer),
Person("may", Sex.Female, Job.Engineer)
)
String format
toStringが値等に応じて実装されていればこの方法が楽そうです。
persons.groupBy { "${it.sex}-${it.job}" }
> {
Male-Engineer=[Person(name=mike, sex=Male, job=Engineer)],
Male-Sales=[Person(name=bob, sex=Male, job=Sales)],
Male-Marketer=[Person(name=sam, sex=Male, job=Marketer)],
Female-Sales=[Person(name=lisa, sex=Female, job=Sales)],
Female-Engineer=[Person(name=alice, sex=Female, job=Engineer), Person(name=may, sex=Female, job=Engineer)]
}
Pair等のObjectに入れる
enumのようにオブジェクトが一意であれば、equalsが実装されたコンテナオブジェクトにいれてもいいと思います。
persons.groupBy { Pair(it.sex, it.job) })
> {
(Male, Engineer)=[Person(name=mike, sex=Male, job=Engineer)],
(Male, Sales)=[Person(name=bob, sex=Male, job=Sales)],
(Male, Marketer)=[Person(name=sam, sex=Male, job=Marketer)],
(Female, Sales)=[Person(name=lisa, sex=Female, job=Sales)],
(Female, Engineer)=[Person(name=alice, sex=Female, job=Engineer), Person(name=may, sex=Female, job=Engineer)]
}
まとめ
まあ、特に特別なことはなかったですね。
個人的にはオブジェクトに入れるほうがmapのkeyを参照し直すときに便利そうなので、好きでした。
ちょっと迷ったのでメモしておきました。
他にもいい方法があったら教えてください。