【问题标题】:Why .map on a mutableList doesn't actually change values inside of List in Kotlin?为什么 mutableList 上的 .map 实际上并没有改变 Kotlin 中 List 内的值?
【发布时间】:2018-04-02 10:28:32
【问题描述】:

这是我所拥有的,也是我想要实现的:

  1. 我有一个类有一个mutableList 作为一个字段。

  2. 我想在该列表中找到一个特定元素并对其进行更改。

这是我迄今为止尝试过的:

  1. 这是我希望的功能声明,在我也将它放入扩展函数之后:

    fun Classroom.setNewParameters(id: String, modifiedName: String) {
        this.students.filter { l -> l.id == id }
                     .map { l -> l.name = modifiedName }
                     .toList()
    }
    

    但列表students 在调用此函数后似乎没有变化。

  2. 我用下面的代码找到了一个“丑陋”的解决方案:

    fun Classroom.setNewParameters(id: String, modifiedName: String) {
        for (l : Student in this.students) {
            if (l.id == id) {
                l.name = modifiedName
                break
            }
        }
    }
    

不过,我真的很想知道为什么第一段代码的行为与它一样,实际上对列表没有任何影响。

【问题讨论】:

  • 我无法重现(但您正在严重滥用 map():没有理由仅仅为了改变原始列表的元素之一而创建新列表)。 gist.github.com/jnizet/a25b87ff33ca156f446adbc8d6548bac。发布一个完整的最小程序来重现您的问题。
  • @JBNizet 是的,你说得对,这完全不酷。我不知道为什么我被 .map 卡住了(实际情况稍微复杂一些,但使用 .map 仍然没有意义)。我在下面发布了一个很好的答案,但他删除了它,无论如何他只是告诉我去students.forEach({ if (it.id == id) it.name = modifiedName }),这似乎工作得很好!你认为这也是一个好的解决方案吗?
  • 没有。我认为您应该使用list.find { it.id == id }?.name = modifiedName。这与您的第二个 sn-p 匹配:找到具有给定 id 的 first 元素,并更改其名称。
  • @JBNizet 如果我需要更新多个值,我该如何应用您的解决方案?即我需要同时编辑姓名和姓氏?除了多次重复查找操作(我猜这很糟糕)之外,我想不出别的办法
  • list.find { it.id == id }?.apply { name = modifiedName; surName = modifiedSurname }

标签: kotlin


【解决方案1】:

您可以将map 视为一种转换输入以获得新输出的方法。通常它不应该在内部改变状态,也就是说它应该是一个没有副作用的函数来追求可维护性

在您的情况下,您显然想要改变元素,为此您可能想要使用该代码 sn-p:

fun Classroom.setNewParameters(id: String, modifiedName: String) {
    this.students.filter { l -> l.id == id }
                 .onEach { l -> l.name = modifiedName }
}

此外,即使您错误地使用了map,它也应该必须修改字段l.name(除非您已经实现了自己的委托或getter/setter)。尝试在this.students.filter { l -> l.id == id }上调试设置断点,看看过滤后是否还有剩余项

【讨论】:

    【解决方案2】:

    这里是新手,但前几天我确实看到了与此相关的东西。

    您是否有理由不只是检查您的数组是否包含旧值,返回元素 id,然后将新值分配给该 id?

    我想我只是指出这可以通过“数组中的值”类型搜索来完成...但我还是太新了,不知道使用它与 map 的优缺点。

    有点像下面这样,我从Kotlin - Idiomatic way to check array contains value得到的


    数组中的“值”

    翻译成 Java API:

    array.contains("值")


    所以我会检查数组中的旧值,返回它的索引,然后用新值重新分配该索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多