从两个列表中获取不常见的元素 - KOTLIN

San*_*oop 8 android list kotlin

我有两个相同的模型类(STUDENT)列表,下面给出了示例学生对象结构,

{
    "_id": "5a66d78690429a1d897a91ed",
        "division": "G",
        "standard": "X",
        "section": "Secondary",
        "lastName": "Sawant",
        "middleName": "Sandeep",
        "firstName": "Shraddha",
        "pin": 12345,
        "isEditable": true,
        "isTracked": false
}
Run Code Online (Sandbox Code Playgroud)

一个列表有3个对象,另外2个.比方说,列表A有1,2,3个学生,列表B有1,2个

所以我的问题是有任何内置函数通过比较id来获取不常见的元素吗?如果不是我怎么能解决这个问题.

仅供参考,以下是我要解决的两种方法,但却失败了.

方法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)
}
Run Code Online (Sandbox Code Playgroud)

方法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)
}
Run Code Online (Sandbox Code Playgroud)

任何形式的帮助将不胜感激.

谢谢

小智 22

我知道这是一篇旧帖子,但我相信有一个更简洁更短的解决方案。使用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())
Run Code Online (Sandbox Code Playgroud)

  • 仅当您想要 list2 中不在 list1 中的元素时,此方法才有效。它不是两个列表的“不同元素”的结果。list1.toSet().minus(list2.toSet()) 没有给出任何元素,所以要小心使用这个答案。 (4认同)

Mik*_*x6r 16

更多的Kotlin方式来实现Ahmed Hegazy发布的内容.地图将包含元素列表,而不是键和计数.

使用HashMap和Kotlin内置插件.groupBy使用Lambda中定义的键创建一个Map(在本例中为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 }
Run Code Online (Sandbox Code Playgroud)

  • 好的解决方案 :) (2认同)

Pie*_*rek 12

如果您有两个列表,其中元素由某种 id (item.id) 等标识,那么您可以执行以下操作:

fisrtList.filter { it.id !in secondList.map { item -> item.id } }
Run Code Online (Sandbox Code Playgroud)

我假设firstList和secondList自然包含相同类型的对象。


N1h*_*1hk 7

这是一个基本上可以完成您想要的功能的扩展函数。它假设该元素E知道如何识别,例如Student._id在您的示例中:

infix fun <E> Collection<E>.symmetricDifference(other: Collection<E>): Set<E> {
    val left = this subtract other
    val right = other subtract this
    return left union right
}
Run Code Online (Sandbox Code Playgroud)

以下是如何使用它的示例:

val disjunctiveUnion: List<Student> = listA symmetricDifference listB
Run Code Online (Sandbox Code Playgroud)

我为其编写的示例测试用例:

@Test
fun `symmetric difference with one of either set`() {
    val left = listOf(1, 2, 3)
    val right = listOf(2, 3, 4)

    val result = left symmetricDifference right

    assertEquals(setOf(1, 4), result)
}
Run Code Online (Sandbox Code Playgroud)