JPM
JPM

Reputation: 9297

Better Way to Find Missing Object in Second List Then Add It Using Kotlin

I have two lists one from a local DB and another from JSON cloud query. Problem is due to Legacy code the device in the cloud has to be mapped to the type that is stored locally on the DB. (I didn't do this client did). So at some point we add a new object it always comes from local. Due to timing issues and just bad RXJava programming that we can't touch right now, we want to check if its been stored in the cloud. If it is not then we take that object and add it to the list of cloud objects and send an update. We have to send the whole list not just the new one, again client decision on that one. So here is what I have there has to be a cleaner way, I've tried using filter, filterNot, but this seems to work for all the test cases:

val tempList = convertLocalObjectToCloud(Id, localObjectsList)
val differences: MutableList<CloudObject> = mutableListOf()

tempList.forEach {localObject->
    val found = cloudList.find {
        localObject.Id == it.Id
    }

    if (found == null) {
        differences.add(localObject)
    }
}

// add to list only items not found
cloudList += differences  

Must work for all seven test cases,

  1. both lists empty - cloudList has no changes
  2. local list empty - cloudList has no changes
  3. local list and cloud list same - cloudList no changes
  4. cloud list empty - cloudList adds all devices from local
  5. local list has more items than cloud - cloudList adds only those items to its list
  6. cloud list has more items local has less but all repeated in cloud - cloudList no changes(delete coming later)
  7. cloud and local have different sizes and some from local is missing in cloud and some from cloud is missing in local - cloudList only adds those missing that local has...delete coming later.

I wrote a quick JUnit test case with the gist of the function code all in one.

class AddFromLocalDBToCloudTest {
    val localList: MutableList<Quijibo> = mutableListOf()
    val cloudList: MutableList<Quijibo> = mutableListOf()

    fun FindMissingObjects() {
        val differences: MutableList<Quijibo> = mutableListOf()

        localList.forEach { localObject->
            val found = cloudList.find {
                localObject.Id == it.Id
            }

            if (found == null) {
                differences.add(localObject)
            }
        }

        // add to list only items not found
        cloudList += differences
    }

    @Before
    fun setup() {
        localList.add(Quijibo(1, "name 1"))
        localList.add(Quijibo(2, "name 2"))
        localList.add(Quijibo(3, "name 3"))
        localList.add(Quijibo(4, "name 4"))

        cloudList.add(Quijibo(1, "name 1"))
        cloudList.add(Quijibo(2, "name 2"))
        cloudList.add(Quijibo(4, "name 4"))
    }

    @Test
    fun `1 Added Missing in Cloud`() {
        FindMissingObjects()
        assertEquals(4, cloudList.size)
    }

    @Test
    fun `2 Same in Cloud`() {
        cloudList.add(Quijibo(3, "name 3"))
        FindMissingObjects()
        assertEquals(4, cloudList.size)
    }

    @Test
    fun `3 Empty in Local DB`() {
        localList.clear()
        FindMissingObjects()
        assertEquals(3, cloudList.size)
    }

    @Test
    fun `4 Empty in both Lists`() {
        localList.clear()
        cloudList.clear()
        FindMissingObjects()
        assertEquals(0, cloudList.size)
    }

    @Test
    fun `5 Empty in Cloud`() {
        cloudList.clear()
        FindMissingObjects()
        assertEquals(4, cloudList.size)
    }

    @Test
    fun `6 More in Cloud but slightly different in both`() {  // could happen...edge case
        localList.removeAt(3)
        localList.removeAt(0)
        FindMissingObjects()
        assertEquals(4, cloudList.size)
    }

}

data class Quijibo(var Id: Int, var name: String)

Upvotes: 3

Views: 1216

Answers (1)

user
user

Reputation: 7604

You can do this by using filter. The below code keeps only elements from tempList for which all elements of cloudList have different id's, i.e., elements that aren't in cloudList already, and then adds those to cloudList.

cloudList += tempList.filter{ localObject -> 
  cloudList.all{ it.id != localObject.id }
}

Upvotes: 1

Related Questions