同じモデルクラス(学生)の2つのリストがあります。サンプルの学生オブジェクト構造を以下に示します。
{
"_id": "5a66d78690429a1d897a91ed",
"division": "G",
"standard": "X",
"section": "Secondary",
"lastName": "Sawant",
"middleName": "Sandeep",
"firstName": "Shraddha",
"pin": 12345,
"isEditable": true,
"isTracked": false
}
1つのリストには3つのオブジェクトと他の2つがあります。たとえば、リストAには1、2、3の生徒がいて、リストBには1、2があるとします。
だから私の質問は、珍しい要素を取得するための組み込み関数があるidだけを比較することによって?そうでない場合、どうすればこの問題を解決できますか?.
参考までに、私が解決するために作成した2つのアプローチを以下に示しますが、惨めに失敗しました。
アプローチ1。
internal fun getDistinctStudents(studentsList: List<Students>, prefStudents: List<Students>): List<Students> {
val consolidated = prefStudents.filter {
prefStudents.any { students: Students -> it._id == students._id }
}
return prefStudents.minus(consolidated)
}
アプローチ2。
internal fun getDistinctStudents(studentsList: List<Students>, prefStudents: List<Students>): List<Students> {
val consolidatedStudents = studentsList + prefStudents
val distinctStudents = consolidatedStudents.distinctBy{ it._id }
return prefStudents.minus(distinctStudents)
}
どんな助けでも大歓迎です。
ありがとう
Ahmed Hegazyの投稿を達成するためのよりKotlinの方法。マップには、キーとカウントではなく、要素のリストが含まれます。
HashMapおよびKotlinビルトインの使用。 groupBy
は、Lambda(この場合はid)で定義されたキーとアイテムのリスト(このシナリオのリスト)でマップを作成します
次に、リストサイズが1以外のエントリを除外します。
そして最後に、それを単一の生徒リストに変換します(したがって、flatMap呼び出し)。
val list1 = listOf(Student("1", "name1"), Student("2", "name2"))
val list2 = listOf(Student("1", "name1"), Student("2", "name2"), Student("3", "name2"))
val sum = list1 + list2
return sum.groupBy { it.id }
.filter { it.value.size == 1 }
.flatMap { it.value }
これはHashMapを使用したソリューションです。コードの方が優れている可能性がありますが、kotlinは非常に初めてです
fun getDistinctStudents(studentsList: List<Student>, prefStudents: List<Student>): List<Student> {
val studentsOccurrences = HashMap<Student, Int>()
val consolidatedStudents = studentsList + prefStudents
for (student in consolidatedStudents) {
val numberOfOccurrences = studentsOccurrences[student]
studentsOccurrences.put(student, if(numberOfOccurrences == null) 1 else numberOfOccurrences + 1)
}
return consolidatedStudents.filter { student -> studentsOccurrences[student] == 1 }
}
生徒のクラスは、データクラスであるか、少なくともハッシュコードをオーバーライドし、キーとして使用するために等しい必要があります。
私はこれが古い記事であることを知っていますが、より簡潔で短い解決策があると思います。上記で回答が承認されたMikezx6rのデータを使用して、以下のサンプルを参照してください。
val list1 = listOf(Student("1", "name1"), Student("2", "name2"))
val list2 = listOf(Student("1", "name1"), Student("2", "name2"), Student("3", "name2"))
val difference = list2.toSet().minus(list1.toSet())
最後に、Kotlinのドキュメントを検索した結果、解決策が見つかりました。私が探していた関数はfilterNot
でした
これが私が試した完全なソリューションです。
internal fun getDistinctStudents(studentsList: List<Students>, prefStudents: List<Students>): List<Students> {
return prefStudents.filterNot { prefStudent ->
studentsList.any {
prefStudent._id == it._id
}
}
}
珍しい要素を返しました。
誰かがより簡潔で短い解決策を思い付くまで、これは私が読むのに十分簡単だと思う実用的な解決策です:
internal fun getDistinctStudents(studentsList: List<Students>, prefStudents: List<Students>): List<Students> {
val studentsIds = studentsList.map { it._id } // [ 1, 2, 3 ]
val prefStudentIds = prefStudents.map { it._id } // [ 1, 2 ]
val commonIds = studentsIds.intersect(prefStudentIds) // [ 1, 2 ]
val allStudents = studentsList + prefStudents // [ Student1, Student2, Student3, Student1, Student2 ]
return allStudents.filter { it._id !in commonIds } // [ Student3 ]
}
非常に大量の学生(数百人)がいる場合は、さまざまなステップにシーケンスを使用することを検討してください。最後の2つのリストを連結する前にフィルタリングすることも役立つ場合があります。
val filteredStudents = studentsList.filter { it._id !in commonIds }
val filteredPrefStudents = prefStudents.filter { it._id !in commonIds }
return filteredStudents + filteredPrefStudents
編集: 代わりにこの答え を参照してください。
現時点ではモバイルなのでテストできませんが、これはあなたが必要とするものでうまくいくかもしれません。 stdlibからの減算の使用 https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/subtract.html
internal fun getDistinctStudents(studentsList: List<Students>, prefStudents:
List<Students>): List<Students> {
return prefStudents.subtract(studentList) + studentList.subtract(prefStudents)
}