Home > Back-end >  Compare two array lists of obejcts with different ids
Compare two array lists of obejcts with different ids

Time:12-03

What is the most optimized way to compare two ArrayLists of different object type? Let's say I have an Array Lists of Remedies and Adherences and them being:

ObjectA

data class Remedies(val data: List<Remedy> = emptyList()) {

    data class Remedy(
        val _id: String,
        val remedy_id: String,
        val patient_id: String,
        val date_created: Long,
        val is_ongoing: Boolean?,
        val start_date: Long,
        val medicine_id: String,
        val instruction: String,
        val medicine_name: String,
        val medicine_type: String,
        val end_date: Long,
        val repeat_cycle: Int,
        val allow_edit: Boolean,
        //val schedule: List<Schedule>?,
        val is_current: Boolean,
        //val medicine: Medicine?,
        val price: Float
    )
}

ObjectB

data class Adherences(val data: List<Adherence> = emptyList()) {

    data class Adherence(
        val _id: String,
        val adherence_id: String,
        val patient_id: String,
        val remedy_id: String,
        val alarm_time: String,
        val action: String,
        val action_time: String,
        val dose_discrete: String,
        val dose_quantity: Int,
        val note: String
    )
}

How can I compare both those two array lists "remedyList" and "adherencesList" where remedy_id is the same and remove items in adherencesList when remedy_id is not present in remedyList.

CodePudding user response:

This should work:

Prepare the input

data class Rdata (val r_id:String)
data class Adata (val a_id:String,val r_id:String)
val rList = (1..10).map {  Rdata("$it")}
val aList = (5..20).map {  Adata("foo", "$it")}

Do the filtering:

val rIds = rList.map { it.r_id }.toSet()
val resultList = aList.filter { it.r_id in rIds}

After this, the resultList contains objects with r_id 5-10. (that is, 11-20 have been removed)

CodePudding user response:

Try this code:

val allRemedies = remedies.flatMap { it.data }.associateBy { it.remedy_id }
val allAdherences = adherences.flatMap { it.data }.associateBy { it.remedy_id }
val allPairs = allAdherences.mapValues { allRemedies[it.key] to it.value }

Playground example

  • remedies is the List<Remedies> and adherences is the List<Adherences>
  • First we flatten the List<Remedies> to List<Remedy> and associate each Remedy to its remedy_id. allRemedies is Map<String, Remedy>.
  • Similarly for the adherences, we prepare a Map<String, Adherence>
  • Then we map each value of allAdherences map to a pair of Remedy? and Adherence. If there is no Remedy for that remedy_id it will be null.

CodePudding user response:

If all you care about is filtering Adherences that don't have a matching Remedy, you can create a Set of remedy_ids from the Remedy List, and use that to efficiently check if they exist and filter on that.

val validRemedyIds: Set<String> = remedies.data.mapTo(mutableSetOf(), Remedy::remedy_id)
val filteredAdherences = Adherences(adherences.data.filter { it.remedy_id in validRemedyIds })

If you need to match them up later, you should use a map instead of set:

val remediesById = remedies.data.associateBy(Remedy::remedy_id)

And then there are several ways you can combine to compare. One example:

val adherencesToRemedies: List<Pair<Adherence, Remedy>> = 
    adherences.data.mapNotNull { remediesById[it.remedy_id]?.run { it to this } }
  • Related