如何在 Kotlin 中从列表中删除某些元素

7

我遇到了一个问题,如何删除不符合特定参数的元素。例如,我有两个数据类:First和Second。First包含了Second的属性,例如城市、价格等:

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)

Item的第二个数据类:

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

我正在使用以下代码从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) }

这是JSON文件:
[
    {
        "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"
    }
]

所以,我想要对其进行过滤。如果用户匹配“纽约”,则列表中必须只有“city”:“纽约”的项目。是的,这只是一个例子,请不要注意我写的所有愚蠢:D

或者当我添加它们时就应该过滤项目?但如果是这样,那么该如何操作呢?


你似乎缺少了一个关键的问题,耐心等待我,我会为你编写一个解决方案... - Thomas Cook
3个回答

13

以下是一个示例,说明如何在原地从列表中删除满足特定条件的项目。该示例从整数列表中删除偶数。

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

输出:

[1, 3, 5, 7, 9]

谢谢!我正在看循环、流和迭代器以及if语句。太简单了! - allenjom
这是一个惊人的解决方案!谢谢! - Michel Fernandes

3
这里有一个解决方案。请注意,在您的OP中,您实际上没有从Product类引用Properties类(因此您无法通过代码筛选出具有属性的产品,因为它们之间没有任何关系)。同时,您正在使用var。具有var的属性是可变的(意味着它们可以在对象创建后更改)。通常最好使用val,如果您需要改变对象的某个属性,请创建一个包含更新后属性的新实例(这对于多线程和异步代码来说更好)。
@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))
}

嗯,我尝试了一下并发现了一些问题。请不要责备我,只是现在我才知道这种可能性。所以,我发现我可以只使用removeIf({s -> s.city != MainActivity.props.city})(问题是我在MainActivity中填充属性)。而且它有效。但是,这个解决方案可行吗?(呵呵) - Arsen Saruhanyan
哎呀,它只支持Android Nougat。 - Arsen Saruhanyan
我不知道removeIf,但是听起来它会从被调用的列表中删除元素(而filter则创建一个新列表,其中过滤掉了元素)。一般来说,这些类型的函数被称为高阶函数,因为它们将一个函数作为输入。例如,filter函数接受一个返回布尔值的函数。然后它在列表中的每个元素上调用传递的函数,如果它返回true,则将该元素添加到新列表中,否则跳过。传递给filter的函数称为“谓词”。 - Thomas Cook
哦,好吧。我想我已经弄明白了。谢谢,这很有帮助。 - Arsen Saruhanyan
没问题,练习在不同的集合上使用这些高阶函数。 - Thomas Cook
嘿@ThomasCook,如果每个产品都有一系列属性,我们如何过滤/删除属性? - Ajay

0
您可以使用以下代码片段删除具有城市名称为纽约("city": "New York")的条目。
productList.removeAll{ product -> product.city == "New York" }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接