2017-06-28 6 views
2

私はインターフェースを実装するオブジェクトは2つありますが、それ以外は無関係です。他のリストの値と一致するリストのオブジェクトのみを含むオブジェクトの新しいコレクションを作成するにはどうすればよいですか?明らかに私はforループを使用することができる&これを手動で行うが、私はKotlinの標準ライブラリコレクションフィルタリング関数を使ってこれをどうやって行うことができるか知りたい。私はドキュメントを読んできましたが、私はfilterToを使用する必要があると確信していますが、述語や変換を設定する方法がわかりません。また、Kotlinにはまだよく分かっていないので、 。各タイプの値を比較して、異なるタイプの2つのリストから新しいリストを作成します。

私はので、ここでの例ですが、理にかなっている段落に達成するために私が好きなものを入れて正確にどのように考え出す苦労のビットを持っている:

interface Ids 
{ 
    val id: Int 
} 

data class A(override val id: Int, val name: String) : Ids 
data class B(override val id: Int, val timestamp: Long) : Ids 

fun main(args: Array<String>) { 
    val a1 = A(1, "Steve") 
    val a2 = A(2, "Ed") 
    val aCol = listOf(a1, a2) 

    val b2 = B(2, 12345) 
    val b3 = B(3, 67890) 
    val bCol = listOf(b2, b3) 

    val matches = mutableListOf<B>() 
    // This is where I'm stuck. 
    // I want to filter bCol using objects from aCol as a filter. 
    // The result should be that matches contains only a single object: b2 
    // because bCol[0].id == aCol[1].id 
    // I'm guessing I need to start with something like this: 
    bCol.filterTo(matches) { ??? } 
} 

答えて

4

直接的なアプローチを考えbColに各bで同じIDを持つオブジェクトに対してaColを検索すること:

bCol.filter { b -> aCol.any { a -> a.id == b.id } } 

しかし、あなたのリストは十分な大きされている場合は、あまりにも遅くなるかもしれません。

val aColIds = aCol.map { it.id }.toSet() 

そしてb.idaColIdsであるかどうかを判断するためにSet.containsメソッドを使用します:

bCol.filter { it.id in aColIds } 
// or equivalent 
bCol.filter { aColIds.contains(it.id) } 
+1

私が巻き上げられ、それがよりスケーラブルあなたが最初aCol内のすべてのIDのセットを構築することができるようにするに

これを私が望んだことにする: 'bCol.filterTo(マッチ){aCol.map {it.id} .contains(it.id)}'。それがパフォーマンスとあなたの答えにどのような影響を与えるかについての考えはありますか?この特定の例では、私は決して大規模なデータセット(<128アイテム)を持つことはありません。 –

+1

@JordanBondoこれは、 'aCol.map'が' bCol'のすべての項目に対して呼び出され、結果が破棄されるため、最初のアプローチよりもさらに遅くなります。したがって、計算の複雑さを増やすだけでなく、大きなメモリコストを課します。 – Ilya

+0

この問題を抱えている人は、大きなデータ(1mil)と小さなデータ(256)の両方でテストを行い、@ Ilyaのソリューションは実際には私よりもずっと高速ですが、 'filterTo'ではなく' filterTo'大幅なパフォーマンス向上。 –

関連する問題