LoginSignup
2
1

More than 3 years have passed since last update.

KotlinのgroupByを複数keyでやる

Posted at

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を参照し直すときに便利そうなので、好きでした。

ちょっと迷ったのでメモしておきました。
他にもいい方法があったら教えてください。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1