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

这是官方文件说的

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开发人员(不是function程序员)不会理解这一点!

我非常简单(对于非function性方法)的情况。

 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 第三名的元素有其计数设置为4

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

 list = list.update( list.findIndex(function(item) { return item.get("name") === "third"; }), function(item) { return item.set("count", 4); } ); 

PS这并不总是可以使用地图。 例如,如果名称不是唯一的,我想更新具有相同名称的所有项目。

使用.setIn()你可以做同样的事情:

 let arr = 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} ] }); arr = arr.setIn(['elem', 3, 'count'], 4); 

如果我们不知道我们想要更新的条目的索引。 使用.findIndex()很容易find它:

 const indexOfListToUpdate = arr.get('elem').findIndex(listItem => { return listItem.get('name') === 'third'; }); arr = arr.setIn(['elem', indexOfListingToUpdate, 'count'], 4); 

希望能帮助到你!

这里是官方文档说… updateIn

你不需要updateIn ,这只适用于嵌套结构。 您正在寻找update方法 ,它有一个更简单的签名和文档:

返回一个新的列表,在索引处具有更新的值,返回值是使用现有值调用updater;如果没有设置索引,则返回notSetValue。

 update(index: number, updater: (value: T) => T): List<T> update(index: number, notSetValue: T, updater: (value: T) => T): List<T> 

其中,如Map::update文档所示,“ 等同于: list.set(index, updater(list.get(index, notSetValue))) ”。

名称为“第三”的元素

这不是列表的工作方式。 您必须知道要更新的元素的索引,否则您必须search它。

我怎样才能更新名单第三名的元素有其计数设置为4?

这应该做到这一点:

 list = list.update(2, function(v) { return {id: v.id, name: v.name, count: 4}; }); 
 var index = list.findIndex(item => item.name === "three") list = list.setIn([index, "count"], 4) 

说明

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

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

 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”方法。 例如setsetIn 。 这些“In”方法不接受索引或键作为第一个参数,而是接受“键path”。 关键path是一个索引或键的数组,说明如何获得您希望更新的值。

在您的示例中,您想要更新索引2处列表中的项目,然后更新该项目中键值“count”处的值。 所以关键path是[2, "count"]setIn方法的第二个参数就像set一样,它是我们想要放在那里的新值,所以:

 list = list.setIn([2, "count"], 4) 

find正确的关键path

更进一步,你实际上说你想更新名称是“三”的项目,这是不同于第三项。 例如,也许你的列表没有sorting,或者可能有名为“two”的项目被删除了? 这意味着首先我们需要确保我们确实知道正确的关键path! 为此我们可以使用findIndex()方法(顺便说一下,它几乎和Array#findIndex一样 )。

一旦我们在列表中find了需要更新的项目的索引,我们就可以为我们希望更新的值提供关键path:

 var index = list.findIndex(item => item.name === "three") list = list.setIn([index, "count"], 4) 

NB: SetUpdate

原来的问题提到更新方法,而不是设置的方法。 我将解释该函数中的第二个参数(称为updater ),因为它与set()不同。 虽然set()的第二个参数是我们想要的新值,但update()的第二个参数是一个接受前一个值并返回我们想要的新值的函数。 然后, updateIn()是接受关键path的update()的“In”变体。

举例来说,我们希望您的示例的变体不只是将计数设置为4 ,而是增加了现有计数,我们可以提供一个函数,将现有值加1:

 var index = list.findIndex(item => item.name === "three") list = list.updateIn([index, "count"], value => value + 1) 

使用.map()

 list = list.map(item => item.get("name") === "third" ? item.set("count", 4) : item ); 
 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.fromJS(arr); var newList = list.map(function(item) { if(item.get("name") === "third") { return item.set("count", 4); } else { return item; } }); console.log('newList', newList.toJS()); // More succinctly, using ES2015: var newList2 = list.map(item => item.get("name") === "third" ? item.set("count", 4) : item ); console.log('newList2', newList2.toJS()); 
 <script src="ajax/libs/immutable/3.8.1/immutable.js"></script> 

你可以使用map

 list = list.map((item) => { return item.get("name") === "third" ? item.set("count", 4) : item; }); 

但是这将迭代整个集合。