世间自有公道,付出总有回报,说到不如做到,要做就做好,步步高!

【译】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"]]]

合并可能会非常棘手,有时候会让你头脑发热,尤其是对于深度嵌套的列表。但是,使用自己的冲突解决功能的能力为操纵数据提供了强大的机制。

posted @ 2017-12-10 11:14  疯狂秀才  阅读(1989)  评论(0编辑  收藏  举报