首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何用ImmutableJS更新列表中的元素?

如何用ImmutableJS更新列表中的元素?
EN

Stack Overflow用户
提问于 2015-04-12 21:01:51
回答 7查看 84.8K关注 0票数 133

以下是官方文件所说的

代码语言:javascript
复制
updateIn(keyPath: Array<any>, updater: (value: any) => any): List<T>
updateIn(keyPath: Array<any>, notSetValue: any, updater: (value: any) => any): List<T>
updateIn(keyPath: Iterable<any, any>, updater: (value: any) => any): List<T>
updateIn(keyPath: Iterable<any, any>, notSetValue: any, updater: (value: any) => any): List<T>

普通的web开发人员(不是函数式程序员)是不可能理解的!

我有一个非常简单的案例(对于非函数方法)。

代码语言:javascript
复制
var arr = [];
arr.push({id: 1, name: "first", count: 2});
arr.push({id: 2, name: "second", count: 1});
arr.push({id: 3, name: "third", count: 2});
arr.push({id: 4, name: "fourth", count: 1});
var list = Immutable.List.of(arr);

如何更新list,其中名为third的元素的count设置为4

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2015-04-16 00:07:13

最合适的情况是同时使用findIndexupdate方法。

代码语言:javascript
复制
list = list.update(
  list.findIndex(function(item) { 
    return item.get("name") === "third"; 
  }), function(item) {
    return item.set("count", 4);
  }
); 

附注:使用地图并不总是可行的。例如,如果名称不是唯一的,而我想要更新具有相同名称的所有项目。

票数 125
EN

Stack Overflow用户

发布于 2016-09-30 17:46:20

使用.setIn()也可以做到这一点:

代码语言:javascript
复制
let obj = fromJS({
  elem: [
    {id: 1, name: "first", count: 2},
    {id: 2, name: "second", count: 1},
    {id: 3, name: "third", count: 2},
    {id: 4, name: "fourth", count: 1}
  ]
});

obj = obj.setIn(['elem', 3, 'count'], 4);

如果我们不知道要更新的条目的索引。使用.findIndex()可以很容易地找到它

代码语言:javascript
复制
const indexOfListToUpdate = obj.get('elem').findIndex(listItem => {
  return listItem.get('name') === 'third';
});
obj = obj.setIn(['elem', indexOfListingToUpdate, 'count'], 4);

希望它能帮上忙!

票数 40
EN

Stack Overflow用户

发布于 2016-12-03 04:16:51

代码语言:javascript
复制
var index = list.findIndex(item => item.name === "three")
list = list.setIn([index, "count"], 4)

说明

更新Immutable.js集合总是返回这些集合的新版本,保持原始版本不变。正因为如此,我们不能使用JavaScript的list[2].count = 4突变语法。相反,我们需要调用方法,就像我们可能对Java集合类所做的那样。

让我们从一个更简单的例子开始:只计算列表中的计数。

代码语言:javascript
复制
var arr = [];
arr.push(2);
arr.push(1);
arr.push(2);
arr.push(1);
var counts = Immutable.List.of(arr);

现在,如果我们想要更新第三项,一个普通的JS数组可能看起来像:counts[2] = 4。因为我们不能使用突变,并且需要调用一个方法,所以我们可以使用:counts.set(2, 4) -这意味着在索引2处设置值4

深度更新

不过,您给出的示例中包含嵌套数据。我们不能只在初始集合上使用set()

Immutable.js集合有一系列名称以" in“结尾的方法,允许您在嵌套的集合中进行更深层次的更改。大多数常见的更新方法都有一个相关的"In“方法。例如,对于set,就有setIn。这些"In“方法接受”键路径“,而不是接受索引或键作为第一个参数。键路径是一个索引或键的数组,它说明了如何获得您希望更新的值。

在您的示例中,您希望更新列表中索引为2的项目,然后更新该项目中关键字"count“处的值。所以关键路径应该是[2, "count"]setIn方法的第二个参数的工作方式与set类似,它是我们要放入其中的新值,因此:

代码语言:javascript
复制
list = list.setIn([2, "count"], 4)

查找正确的密钥路径

更进一步,你实际上说你想要更新名称为"three“的项目,这与第三个项目不同。例如,可能您的列表没有排序,或者名为"two“的项之前被删除了?这意味着首先我们需要确保我们确实知道正确的密钥路径!为此,我们可以使用findIndex()方法(顺便说一句,它的工作方式与Array#findIndex几乎完全相同)。

一旦我们在列表中找到了包含我们想要更新的项的索引,我们就可以提供我们想要更新的值的键路径:

代码语言:javascript
复制
var index = list.findIndex(item => item.name === "three")
list = list.setIn([index, "count"], 4)

NB: Update vs.

最初的问题提到的是update方法,而不是set方法。我将解释该函数中的第二个参数(称为updater),因为它不同于set()set()的第二个参数是我们想要的新值,而update()的第二个参数是一个函数,它接受前一个值并返回我们想要的新值。然后,updateIn()update()的"In“变体,它接受密钥路径。

例如,我们想要你的例子的一个变体,它不只是将计数设置为4,而是增加现有的计数,我们可以提供一个函数,将现有值加1:

代码语言:javascript
复制
var index = list.findIndex(item => item.name === "three")
list = list.updateIn([index, "count"], value => value + 1)
票数 23
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29589753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档