Home > Software engineering >  Filter a list of object
Filter a list of object

Time:12-10

Let say I have a list of objects:

data class Home(
    var id: String = "",
    var status: MutableMap<String, Double> = mutableMapOf(),
    var userName: String = "",
) 

var myList = listOf(
            Home("1", mutableMapOf("hello", 1.0), "firstUser"), 
            Home("2", mutableMapOf("hello", 2.0), "secondUser"), 
            Home("3", mutableMapOf("goodbye", 3.0), "thirdUser")
)

With this list, I want to implement a search view and I want to filter this list based on the map key or based on the username. For example, if I search for "hello" it will return a list with 2 objects inside:

listOf(Home("1", mutableMapOf("hello", 1.0), "firstUser"), 
       Home("2", mutableMapOf("hello", 2.0), "secondUser"))

I'm trying with no success the code below:

searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
        override fun onQueryTextSubmit(query: String): Boolean {
            return false
        }

        override fun onQueryTextChange(newText: String): Boolean {

            myList.stream()
                .filter { p ->
                       p.userName.lowercase(Locale.getDefault())
                                .contains(newText.lowercase(Locale.getDefault())) ||
                       p.status.keys.contains(newText.lowercase(Locale.getDefault()))
                }
                .collect(Collectors.toList()) 

             adapter.submitList(myList)
        }
    })

Any advice on what I'm doing wrong, please?

EDIT: As @Joffrey said I modified my code so I can use Kotlin filters. I'm filtering by username and it's ok. When I try to filter myList by the map key, I have to insert the whole text to get any result, for example: "hello". At this point, I need to filter the list if the map's key contains a substring.

override fun onQueryTextChange(newText: String): Boolean {

            val filteredList: List<Home> =
                myList.filter {
                    it.userName.lowercase(Locale.getDefault()).contains(newText.lowercase(Locale.getDefault())) ||
                            it.status.keys.contains(newText)
                }
            adapter.submitList(filteredList)

            return false
        }

CodePudding user response:

I have resolved it like this, the function below will find every map in the list whose key contain the desired substring:

    infix fun <V> Map<String, V>.withKeyPart(keyPart: String): List<V> {
        return this.filter { it.key.lowercase(Locale.getDefault()).contains(keyPart) }
        .map { it.value }
}

Then to apply the search view I did like this:

override fun onQueryTextChange(newText: String): Boolean {

            val filteredList: List<Home> =
                myList.filter {
                    it.userName.lowercase(Locale.getDefault()).contains(newText.lowercase(Locale.getDefault())) ||
                            it.status.withKeyPart(newText.lowercase(Locale.getDefault())).isNotEmpty()
                }

            adapter.myList(filteredList)

            return false
        }
  • Related