【译】Immutable.js: 合并 List - 4
在之前的文章中,我们已经看到了如何创建一个新的列表,以及如何添加,插入和删除项目。现在是时候学习更高级一点的技能了 —— 合并两个或更多列表的方式。
注意:记住Immutable不会改变任何被合并的列表。合并列表总是从任何合并函数返回,使合并操作中涉及的任何列表完全不变。因此,无论何时您看到诸如“合并列表...”或“覆盖originalList”之类的词组,它都是被包含的列表的副本,这些副本正在发生变化(并最终作为合并列表返回)。
列表的4个合并功能
Immutable提供了四个独立的合并函数:
originalList.merge(List1, List2, List3...List-n)
通过用List1(和List2,List3 ... List-n)中的项目覆盖originalList
的相应位置上的每个项目,返回合并列表。mergeWith(conflictResolutionFn, List1, List2, List3...List-n)
将列表合并在一起,但使用传入的conflictResolutionFn()来解决冲突.mergeDeep(List1, List2, List3...List-n)
将列表合并在一起,如果存在冲突,则合并冲突项目mergeDeepWith(conflictResolutionFn, List1, List2, List3...List-n)
将列表合并在一起,如果存在冲突,则使用传入的conflictResolutionFn()来解决冲突。
以下是如何使用这些功能。
merge()
合并两个列表
merge()
使用合并列表中存在于相应索引处的值覆盖List中每个项目的值。
// Merge two lists together with merge
const oldAvengers = Immutable.List(['ironMan', 'captainAmerica', 'theHulk']);
const newAvengers = Immutable.List(['scarletWitch', 'vision']);
// Merge all the lists!
oldAvengers.merge(newAvengers);
这是发生了什么事情:
oldAvengers[0] = 'ironMan'
newAvengers[0] = 'scarletWitch'
- 列表中的每个项目(即oldAvengers)的值被相应索引(即索引0)处的合并列表(即newAvengers)中的值覆盖。
- 所以,'scarletWitch'(newAvengers [0]处的值)会覆盖'ironMan'(oldAvengers [0]处的值)。 'vision'重写'captainAmerica';但新的newAvengers[2]并不存在,所以oldAvengers[2](即“theHulk)保持不变。
将两个以上的列表合并在一起
将两个以上的列表合并在一起时,列表将依次合并,最后一个列表最终将覆盖所有以前的列表。
// Merge more than one List together
const oldAvengers = Immutable.List(['ironMan', 'captainAmerica', 'theHulk']);
const newAvengers = Immutable.List(['scarletWitch', 'vision']);
const newerAvengers = Immutable.List(['antMan']);
// Merge all the lists!
oldAvengers.merge(newAvengers, newerAvengers);
mergeWith()
mergeWith()
让您提供自己的冲突解决功能,这样您就可以使合并更加智能化,而不仅仅是通过索引值覆盖,并且更加具体地满足您的需求。使用方法:
list1.mergeWith(conflictResolutionFn(list1Value, list2Value, index){}, list2)
示例
1、合并列表并根据项目值解决冲突
// Merge lists only if item is not null with mergeWith()
const oldAvengers = Immutable.List(['ironMan', 'captainAmerica', 'theHulk']);
const newAvengers = Immutable.List(['scarletWitch', null, 'vision']);
// Merge only if newAvenger value is not null
oldAvengers.mergeWith((oldAvenger, newAvenger, index) => {
return (newAvenger === null) ? oldAvenger : newAvenger
}, newAvengers);
2、根据索引合并列表并解决冲突
// Merge every other List item with mergeWith()
const oldAvengers = Immutable.List(
['ironMan', 'captainAmerica', 'blackWidow', 'theHulk']
);
const newAvengers = Immutable.List(
['scarletWitch', 'vision', 'antMan', 'falcon']
);
// Merge every other item
oldAvengers.mergeWith((oldAvenger, newAvenger, index) => {
return (index % 2) ? newAvenger : oldAvenger
}, newAvengers);
mergeDeep()
merge 做啥 mergeDeep 就干啥,但是对于嵌套列表,可以迭代线个层次中的项。
合并两个嵌套列表,让Immutable解决冲突
merge()使用相应索引处存在的合并List中的值覆盖List中每个项目的值。但是,在嵌套列表的情况下,这可能会覆盖整个嵌套List,而不是单个项目。
-- Demo
// Merge two nested Lists together with merge()
const oldAvengers = Immutable.fromJS(
[
['ironMan', ['captainAmerica']],
['theHulk', ['Thor']]
]);
const newAvengers = Immutable.fromJS(
[
['vision'],
[
['blackWidow']
]
]);
// This overwrites everything in oldAvengers
oldAvengers.merge(newAvengers);
** output: **
[["vision"], [["blackWidow"]]]
newAvengers List项目覆盖oldAvengers中的所有相应项目(例如'vision'覆盖'ironMan'和嵌套List'captainAmerica')。
要保留一个List的嵌套,并针对一个特定的嵌套级别,你需要使用mergeDeep:
// Merge two nested Lists together with mergeDeep()
const oldAvengers = Immutable.fromJS(
[
['ironMan', ['captainAmerica']],
['theHulk', ['Thor']]
]);
const newAvengers = Immutable.fromJS(
[
['vision'],
[
['blackWidow']
]
]);
// This leaves the nested Lists intact
oldAvengers.mergeDeep(newAvengers);
OUTPUT *********************************************************
[["vision", ["captainAmerica"]], [["blackWidow"], ["Thor"]]]
mergeDeepWith()
如果您需要自行决定应该合并哪个嵌套项目,请使用mergeDeepWtih:
将两个嵌套列表合并在一起,自己解决冲突
list1.mergeDeepWith(conflictResolutionFn(list1Value, list2Value, index){}, list2)
// Merge two nested Lists together with mergeDeepWith()
const oldAvengers = Immutable.fromJS(
[
['ironMan', ['captainAmerica']],
['theHulk', ['Thor']]
]);
const newAvengers = Immutable.fromJS(
[
['vision'],
['blackWidow', 'Loki']
]);
// Loki can't replace Thor
oldAvengers.mergeDeepWith((prev, next, index) => {
return (next === 'Loki') ? prev : next
}, newAvengers);
OUTPUT ************************************************************
[["vision", ["captainAmerica"]], ["blackWidow", ["Thor"]]]
合并可能会非常棘手,有时候会让你头脑发热,尤其是对于深度嵌套的列表。但是,使用自己的冲突解决功能的能力为操纵数据提供了强大的机制。