Home > Back-end >  Drop list if element found in nested list in kotlin
Drop list if element found in nested list in kotlin

Time:06-11

Hey I have a huge list coming from server. I am adding some data at top of list. I want to remove data from the list. I have nested list in which I need to find the element in nested list.

fun categoriesList() = listOf(
    Categories("21", "physical", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
    Categories("2211", "mind", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
    Categories("22131", "motorized", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
    Categories("2134124", "coordination", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
    Categories("211243", "animal-supported", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
)

Categories.kt

data class Categories(
    val id: String? = null, val title: String? = null, val subTopic: List<SubTopic>? = null
)

SubTopic.kt

data class SubTopic(
    val id: String? = null, val title: String? = null, var priceId: String? = null
)

main.kt

var categoryList: List<Categories>? = null

fun main() {
    categoryList = categoriesList()
    categoryList?.add(0, Categories("0", "physical-ktm", listOf(SubTopic("1", "vivek"))))
}

So I want to find title = "Vivek" if that found I want to drop my whole list index 0 element data. Important I only need to check element at index 0. I don't want to iterate whole list. If found the data in index 0 drop it otherwise leave it the iteration. So what is efficient way of doing this in kotlin idiomatic way. Can someone guide me. Thanks

UPDATE

categoryList?.forEachIndexed { index, data->
    println("$index index -> $data")
}

console

0 index -> Categories(id=0, title=physical-ktm, subTopic=[SubTopic(id=1, title=vivek, priceId=null)])
1 index -> Categories(id=21, title=physical, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
2 index -> Categories(id=2211, title=mind, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
3 index -> Categories(id=22131, title=motorized, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
4 index -> Categories(id=2134124, title=coordination, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
5 index -> Categories(id=211243, title=animal-supported, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])

I only want to search in 0 index of Categories and if title = "vivek" is found in subTopic then I want to drop 0 index from Categories and stop iteration. If data is not found at all in subTopic then I don't won't to iterate whole list of Categories.

After @Tenfour04 suggestion I added this code

var categoryList: MutableList<Categories>? = null
fun main() {
    categoryList = categoriesList().toMutableList()
    categoryList?.add(0, Categories("0", "physical-ktm", listOf(SubTopic("1", "vivek"))))
    println("After Add")
    categoryList?.forEachIndexed { index, categories ->
        println("$index index -> $categories")
    }

    val matchingIndex = categoryList?.indexOfFirst { it.subTopic?.first()?.title == "vivek" }
    if (matchingIndex != null && matchingIndex >= 0) {
        categoryList = categoryList?.mapIndexed { index, it ->
            if (index == matchingIndex)
                it.copy(subTopic = it.subTopic?.drop(1))
            else
                it
        } as MutableList<Categories>?
    }
    println("After operation")
    categoryList?.forEachIndexed { index, categories ->
        println("$index index -> $categories")
    }
}

Actual Output

After Add
0 index -> Categories(id=0, title=physical-ktm, subTopic=[SubTopic(id=1, title=vivek, priceId=null)])
1 index -> Categories(id=21, title=physical, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
2 index -> Categories(id=2211, title=mind, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
3 index -> Categories(id=22131, title=motorized, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
4 index -> Categories(id=2134124, title=coordination, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
5 index -> Categories(id=211243, title=animal-supported, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
After operation
0 index -> Categories(id=0, title=physical-ktm, subTopic=[])
1 index -> Categories(id=21, title=physical, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
2 index -> Categories(id=2211, title=mind, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
3 index -> Categories(id=22131, title=motorized, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
4 index -> Categories(id=2134124, title=coordination, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
5 index -> Categories(id=211243, title=animal-supported, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])

Expect Output

After Add
0 index -> Categories(id=0, title=physical-ktm, subTopic=[SubTopic(id=1, title=vivek, priceId=null)])
1 index -> Categories(id=21, title=physical, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
2 index -> Categories(id=2211, title=mind, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
3 index -> Categories(id=22131, title=motorized, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
4 index -> Categories(id=2134124, title=coordination, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
5 index -> Categories(id=211243, title=animal-supported, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
After operation
0 index -> Categories(id=21, title=physical, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
1 index -> Categories(id=2211, title=mind, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
2 index -> Categories(id=22131, title=motorized, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
3 index -> Categories(id=2134124, title=coordination, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])
4 index -> Categories(id=211243, title=animal-supported, subTopic=[SubTopic(id=1, title=abc, priceId=null), SubTopic(id=2, title=bjhef, priceId=null)])

I want to remove whole Categoriesobject which is present at index 0.

CodePudding user response:

So if I understand the question correctly, you want to eliminate the first – and only the first – subtopic for each category in categoriesList if its title is "Vivek":

data class SubTopic(
  val id: String? = null,
  val title: String? = null,
  var priceId: String? = null
)

data class Categories(
  val id: String? = null,
  val title: String? = null,
  val subTopic: List<SubTopic>? = null
)

val categoriesList = listOf(
  Categories("21", "physical", listOf(SubTopic("1", "abc"), SubTopic("2", "Vivek"))),
  Categories("2211", "mind", listOf(SubTopic("1", "Vivek"), SubTopic("2", "bjhef"))),
  Categories("22131", "motorized", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
  Categories("2134124", "coordination", listOf(SubTopic("1", "Vivek"), SubTopic("2", "Vivek"))),
  Categories("211243", "animal-supported", listOf(SubTopic("1", "abc"), SubTopic("2", "bjhef"))),
)

var categoryList = categoriesList
  .map {
    it.copy(subTopic = it.subTopic
      ?.filterIndexed { index, subTopic -> (index == 0 && subTopic.title != "Vivek") || index > 0 }
    )
  }

categoryList.forEach(::println)

CodePudding user response:

My understood description of the task: Find the first (and only first) Categories in categoriesList that has a subList whose first SubTopic has a title of "vivek". If it is found, set categoriesList to a new List where the Categories where it was found has been replaced with a new Categories instance whose subList has the matched first SubTopic removed.

If prioritizing clarity, I would use map even though it will copy the list regardless of whether any Categories are modified. And I'd use a Boolean variable to determine whether the search must continue.

var itemFound = false
categoriesList = categoriesList.map {
    if (!itemFound && it.subTopic?.first()?.title == "vivek") {
        itemFound = true
        it.copy(subTopic = it.subTopic?.drop(1))
    } else {
        it
    }
}

If prioritizing performance, I would search using indexOf so I would only create the new list if necessary. But really, if performance is truly this critical we really should be using mutable collections and data classes. That might not be possible if doing list comparisons, of course.

val matchingIndex = categories.indexOfFirst { it.subTopic?.first()?.title == "vivek"}
if (matchingIndex >= 0) {
    categoriesList = categoriesList.mapIndexed { index, it ->
        if (index == matchingIndex)
            it.copy(subTopic = it.subTopic?.drop(1))
        else
            it
    }
}

Edit: based on your new comment, I think this is what you are asking for now. Quite a bit simpler.

if(categoriesList.first().subTopics.orEmpty().any { it.title == “vivek” }) {
    categoriesList = categoriesList.drop(1)
}
  • Related