How to delete some elements from list in kotlin

19,301

Solution 1

Here is a solution for you. Notice in your OP you did not actually reference Properties class at all from your Product class (so you wouldn't have been able to filter products by properties because they don't have any relationship in your code).

Also, you are using var. Properties with var are mutable (meaning they can be changed after object creation). It's generally better to use val and, if you need to mutate a property of an object, create a new instance with the updated properties (much better for multithreading and async code).

@Test
fun testFilter() {

    // Properties of a product
    data class Properties(val city: String, val day: Int, val month: Int, val yearProp: Int, val dayEnd: Int, val monthEnd: Int, val yearEndProp: Int, val priceFrom: Int, val priceTo: Int)

    // A product (notice it references Properties)
    data class Product(val productProperties: Properties, val title: String, val price: String, val photoId : String)

    // Let's pretend these came from the server (we parsed them using Gson converter)
    val productA = Product(Properties("New York", 0, 0, 0, 0, 0, 0, 0, 0), "Sweets", "$1", "1")
    val productB = Product(Properties("Boston", 0, 0, 0, 0, 0, 0, 0, 0), "Eggs", "$2", "1")
    val productC = Product(Properties("New York", 0, 0, 0, 0, 0, 0, 0, 0), "Flour", "$1", "1")

    // Create a list of the products
    val listOfProducts = mutableListOf(productA, productB, productC)

    // Filter the products which have new york as the city in their properties
    val filteredNewYorkProducts = listOfProducts.filter { it.productProperties.city == "New York" }

    // Assert that the filtered products contains 2 elements
    Assert.assertTrue(filteredNewYorkProducts.size == 2)

    // Assert that the filtered products contains both product A and B
    Assert.assertTrue(filteredNewYorkProducts.contains(productA))
    Assert.assertTrue(filteredNewYorkProducts.contains(productB))
}

Solution 2

Here is an example to remove items with certain conditions from a list in place. This example removes even numbers from a list of integers.

var myLists = mutableListOf(1,2,3,4,5,6,7,8,9)
myLists.removeAll{ it % 2 == 0 }
println(myLists)

prints:

[1, 3, 5, 7, 9]
Share:
19,301
Arsen Saruhanyan
Author by

Arsen Saruhanyan

Updated on June 24, 2022

Comments

  • Arsen Saruhanyan
    Arsen Saruhanyan almost 2 years

    I had a problem with how to remove elements that do not match certain parameters. For example, I have two data classes: First and Second First one contains properties for second i.e. city, price etc:

    data class Properties(val city: String, val day: Int, val month: Int, val yearProp: Int, val dayEnd: Int, val monthEnd: Int, val yearEndProp: Int, val priceFrom: Int, val priceTo: Int)
    

    Second data class for Item:

    data class Product(var title: String, var price: String, var photoId : String)
    

    I'm parsing data for Products by this code from json:

    val gson = GsonBuilder().setPrettyPrinting().create()
    val inputStream : Reader = context.getResources().openRawResource(R.raw.products).reader()
    var productList: ArrayList<Product> = gson.fromJson(inputStream, object : TypeToken<List<Product>>() {}.type)
    productList.forEach { println(it) }
    

    This is JSON File:

    [
        {
            "city": "New York",
            "title": "Banana",
            "price": "$1,99"
            "photoId": "someurl"
        },
        {
            "city": "New York",
            "title": "Strawberry",
            "price": "$1,99"
            "photoId": "someurl"
        },
        {
            "city": "Philadelphia",
            "title": "Banana",
            "price": "$4,99"
            "photoId": "someurl"
        }
    ]
    

    So, I want to filter it. If user match "New York" then in list must be only items with "city":"New York". And yes, this is just for example, do not pay attention to all the stupidity that I wrote there :D

    Or may be I should filter items when I adding it? But if so, then how to do it?

  • Arsen Saruhanyan
    Arsen Saruhanyan about 6 years
    Hm. I've tried it and found some questions. Please do not scold me, only now I learned about this possibility. So, I've found that I can just use removeIf({ s -> s.city != MainActivity.props.city}) (The problem is that I fill Properties in MainActivity). And it works.But, is this solution ok? (heh)
  • Arsen Saruhanyan
    Arsen Saruhanyan about 6 years
    Ouch. It's Android Nougat-only.
  • Thomas Cook
    Thomas Cook about 6 years
    I don't know removeIf, but, it sounds like it will remove elements from the list it's called on (whereas filter creates a new list with the elements filtered out). In general, these kind of functions are called higher order functions as they take a function as input. For instance, the filter function takes in a function that returns a boolean. It then calls the passed function on each element in the list and if it returns true it adds that element to a new list, else it skips. The function passed into filter is known as a predicate.
  • Arsen Saruhanyan
    Arsen Saruhanyan about 6 years
    Oh, well. I think I figured it out. Thanks, it helps.
  • Thomas Cook
    Thomas Cook about 6 years
    No problem, practice using these higher order functions on different collections.
  • allenjom
    allenjom over 4 years
    Thank you!! I was looking at loops and streams and iterators and if. Too easy!
  • Ajay
    Ajay about 4 years
    hey @ThomasCook how can we filter/remove properties if each product has a list of properties ?
  • Michel Fernandes
    Michel Fernandes over 3 years
    I's an amazing solution! Thanks!