Kotlin code to remove duplicate object of one particular type from mutable list

Viewed 1179

I want to remove all duplicate objects of one type from a list.

For Eg.

 val models: MutableList<Model> = MutableList<DrawableModel>
 models.add(Student)
 models.add(Student)
 models.add(Teacher)
 models.add(Teacher)
 models.add(Teacher)

Expected Output:

Student
Student
Teacher

I want only one instance of a teacher on the list.

I tried with

models.distinctBy{ it is Teacher}

But it is applying distinct to the entire list not to a particular object and returns.

Student
Teacher
3 Answers

You can try something like this:

object Kotlin
{
    @JvmStatic
    fun main(args: Array<String>)
    {
        val teacher = Teacher(0, "T1");
        val student = Student(1, "S1")

        val models = mutableListOf(teacher, teacher, student, student, student)
        
        // creating new list which is connection of two lists. First -> only Students. Second -> Distinct Teacher
        val newModels = models.filterIsInstance<Teacher>().distinct() + models.filterIsInstance<Student>()

        println(models) // [Teacher(ID=0, name=T1), Teacher(ID=0, name=T1), Student(ID=1, name=S1), Student(ID=1, name=S1)]
        println(newModels) // [Teacher(ID=0, name=T1), Student(ID=1, name=S1), Student(ID=1, name=S1)]
}

// classes like in the question.
open class Model(val id: Int)

data class Teacher(val ID: Int, val name: String) : Model(ID)

data class Student(val ID: Int, val name: String) : Model(ID)

So basically it is the main part:

val newModels = models.filterIsInstance<Teacher>().distinct() + models.filterIsInstance<Student>()

Try this:

var list =  arrayListOf<Any>()
    list.add(Person("JAVA",20))
    list.add(Person("JAVA",20))
    list.add(Student("SQL",24))
    list.add(Student("SQL",24))
    list.add(Student("SQL",24))

    var filterList = arrayListOf<Any>()
    var studentCount = 0

    // filtering student object only 
    list.forEach {
        if (it is Student && studentCount == 0) {
            studentCount++
            filterList.add(it)
        } else if (it is Person) filterList.add(it)
    }
    filterList.stream().forEach { println(it) }// output : [JAVA,20],[JAVA,20],[SQL,24]

You can set a Boolean so it skips the first one it finds.

var first = true
models.removeAll { if (it is Teacher) (!first).also { first = false } else false }

If you want a new list, use filterNot instead of removeAll.

distinctBy doesn't work because it's converting the objects to distinct keys. Since you're key type is Boolean, there can only be two items in the list.

Related