Vit*_*kov 126 javascript functional-programming immutable.js
这是官方文档所说的
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>
Run Code Online (Sandbox Code Playgroud)
普通的Web开发人员(非功能程序员)无法理解这一点!
我非常简单(对于非功能性方法)的情况.
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);
Run Code Online (Sandbox Code Playgroud)
如何更新list
名称为third的元素的计数设置为4的位置?
Vit*_*kov 116
最合适的情况是使用两者findIndex
和update
方法.
list = list.update(
list.findIndex(function(item) {
return item.get("name") === "third";
}), function(item) {
return item.set("count", 4);
}
);
Run Code Online (Sandbox Code Playgroud)
PS并不总是可以使用地图.例如,如果名称不唯一,我想更新具有相同名称的所有项目.
Alb*_*ivé 31
使用.setIn()可以执行相同的操作:
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);
Run Code Online (Sandbox Code Playgroud)
如果我们不知道要更新的条目的索引.使用.findIndex()很容易找到它:
const indexOfListToUpdate = obj.get('elem').findIndex(listItem => {
return listItem.get('name') === 'third';
});
obj = obj.setIn(['elem', indexOfListingToUpdate, 'count'], 4);
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你!
Ber*_*rgi 19
这是官方文件说的......
updateIn
您不需要updateIn
,仅适用于嵌套结构.您正在寻找update
方法,它有一个更简单的签名和文档:
返回一个新的List,其索引处的更新值为使用现有值调用updater的返回值,如果未设置index,则返回notSetValue.
Run Code Online (Sandbox Code Playgroud)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)))
".
其中名称为"third"的元素
这不是列表的工作方式.您必须知道要更新的元素的索引,或者您必须搜索它.
如何更新列表,其中名称为third的元素的计数设置为4?
这应该这样做:
list = list.update(2, function(v) {
return {id: v.id, name: v.name, count: 4};
});
Run Code Online (Sandbox Code Playgroud)
Lee*_*ron 17
var index = list.findIndex(item => item.name === "three")
list = list.setIn([index, "count"], 4)
Run Code Online (Sandbox Code Playgroud)
说明
更新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);
Run Code Online (Sandbox Code Playgroud)
现在,如果我们想要更新第3项,那么普通的JS数组可能如下所示:counts[2] = 4
.由于我们不能使用变异,并且需要调用方法,而是我们可以使用:counts.set(2, 4)
- 这意味着4
在索引处设置值2
.
深度更新
您给出的示例包含嵌套数据.我们不能只使用set()
初始集合.
Immutable.js集合有一系列方法,名称以"In"结尾,允许您在嵌套集中进行更深层次的更改.最常见的更新方法具有相关的"In"方法.例如,set
有setIn
.这些"In"方法不接受索引或键作为第一个参数,而是接受"关键路径".关键路径是索引或键的数组,用于说明如何获取要更新的值.
在您的示例中,您希望更新索引2中列表中的项目,然后更新该项目中键"count"的值.所以关键路径是[2, "count"]
.该setIn
方法的第二个参数就像是set
,它是我们想要放在那里的新值,所以:
list = list.setIn([2, "count"], 4)
Run Code Online (Sandbox Code Playgroud)
找到正确的关键路径
更进一步,你实际上说你想要更新名称为"3"的项目,这与第3项不同.例如,您的列表可能没有排序,或者可能之前删除了名为"two"的项目?这意味着首先我们需要确保我们确实知道正确的关键路径!为此,我们可以使用该findIndex()
方法(顺便说一句,它的工作方式与Array#findIndex几乎完全相同).
一旦我们在列表中找到了包含我们想要更新的项目的索引,我们就可以提供我们希望更新的值的关键路径:
var index = list.findIndex(item => item.name === "three")
list = list.setIn([index, "count"], 4)
Run Code Online (Sandbox Code Playgroud)
NB:Set
vsUpdate
原始问题提到了更新方法而不是set方法.我将解释该函数中的第二个参数(称为updater
),因为它与...不同set()
.虽然第二个参数set()
是我们想要的新值,但第二个参数update()
是一个函数,它接受前一个值并返回我们想要的新值.然后,updateIn()
其中"In"变体update()
接受关键路径.
比方说,我们想要一个不只是将计数设置为的示例的变体4
,而是增加现有计数,我们可以提供一个函数,它将现有值加1:
var index = list.findIndex(item => item.name === "three")
list = list.updateIn([index, "count"], value => value + 1)
Run Code Online (Sandbox Code Playgroud)
Mei*_*tro 10
使用.map()
list = list.map(item =>
item.get("name") === "third" ? item.set("count", 4) : item
);
Run Code Online (Sandbox Code Playgroud)
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());
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>
Run Code Online (Sandbox Code Playgroud)