[AD] Scalaアプリケーションの開発・保守は合同会社ミルクソフトにお任せください
Listから重複した要素を削除する方法をご紹介します。
distinctメソッドを使用する
distinctメソッドを使用することで、List内の重複した要素を除いたListを取得することができます。
以下のコードは、distinctメソッドの使用例です。
val list = List("orange", "apple", "banana", "grape", "strawberry", "apple") val result = list.distinct result.zipWithIndex.foreach { case (v, i) => println(s"[${i}] : ${v}") }
実行結果は以下のようになります。
[0] : orange [1] : apple [2] : banana [3] : grape [4] : strawberry
ただし、distinctメソッドで重複を削除することができるのは、==で同じ値かを判定することができる要素を持つListです。
例えば、(String, Int)のタプルを要素に持つListからタプルの第1要素が重複した要素を削除したい場合、distinctメソッドを使ってしまうと第1要素だけを取り出して比較するのではなく要素のタプルそのものを比較することになるため、重複とはみなされません。
val list = List(("orange", 50), ("apple", 100), ("orange", 60), ("apple", 90)) val result = list.distinct result.zipWithIndex.foreach { case (v, i) => println(s"[$i] : ${v._1}=${v._2}") }
実行結果は以下のようになります。
[0] : orange=50 [1] : apple=100 [2] : orange=60 [3] : apple=90
distinctByメソッドを使用する
前述のタプルを要素に持つListから、タプルの第1要素が重複した要素を削除するには、distinctByメソッドを使用します。
以下のように、distinctByメソッドに「List内の要素から重複チェックをする値へと変換する関数 f: (A) => B」を渡します。
これによって、distinctByメソッドに対して「要素の何の値をもとに同値比較するべきか」を指示することができます。
以下の例ではタプルからタプルの第1要素に変換する関数を指定しています。
val list = List(("orange", 50), ("apple", 100), ("orange", 60), ("apple", 90)) val result = list.distinctBy(a => a._1) result.zipWithIndex.foreach { case (v, i) => println(s"[$i] : ${v._1}=${v._2}") }
以下のようにタプルの第1要素で重複を除いたListを取得できます。
[0] : orange=50 [1] : apple=100
foldLeftを使用する
distinctByメソッドは、2.13で追加されたメソッドのため、2.12以前のバージョンでは使用できません。
その場合は、以下のようにfoldLeftメソッドを使用して、List内容重複した要素を取り除きます。
val list = List(("orange", 50), ("apple", 100), ("orange", 60), ("apple", 90)) val result = list.foldLeft(List[(String, Int)]()) {(l, v) => { if(l.exists(e => e._1 == v._1)) l else v :: l }} result.reverse.zipWithIndex.foreach { case (v, i) => println(s"[$i] : ${v._1}=${v._2}") }
以下のように、distinctByメソッドを使用した場合と同じ結果になります。
[0] : orange=50 [1] : apple=100
Setを使用する
さらに別の方法として、Setを使用する方法をご紹介します。
Setは、要素の重複を許さないコレクションです。
最初にListのtoSetメソッドで、ListをSetに変換します。
その後にSetのtoListメソッドでListに変換することで、重複を除いたListを取得できます。
val list = List("orange", "apple", "banana", "grape", "strawberry", "apple") val result = list.toSet.toList result.zipWithIndex.foreach { case (v, i) => println(s"[${i}] : ${v}") }
distinctメソッドを使用した場合と同じように、重複を除いたListを取得できました。
ただし、Set内の要素の順番は保証されません。
したがって一旦Setに変換した以上、この方法で得たListの持つ要素の順番もまた保証されないことに注意しましょう。
[0] : orange [1] : apple [2] : strawberry [3] : banana [4] : grape