Immutable offers many different ways of merging two or more Maps together. Choosing the right way, though, is confusing, unless you have an awesome guide with copious examples – which, funnily enough, is what this tutorial is.

Merging Maps

There are six different ways to merge two or more Maps together. Use them as follows:

  • originalMap.merge(Map1, Map2, Map3, ...Map-n) – merges Maps together adding the key/value pairs of the merging Maps to those of the originalMap. If two keys are duplicated, the last Map’s value is used. Nested Maps are notmerged.
  • originalMap.mergeWith((originalMapValue, mergedMapValue, key) => { /* conflict resolution */ }, Map1, Map2, Map3, ...Map-n); – merges Maps, but lets you control which value to use if there are any conflicts;
  • originalMap.mergeDeep(Map1, Map2, Map3, ...Map-n) – merges Maps, including nested Maps;
  • originalMap.mergeDeepWith((originalMapValue, mergedMapValue, key) => { /* conflict resolution */ }, Map1, Map2, Map3, ...Map-n); – merges Maps deeply, but lets you control which value to use if there are any conflicts;
  • const mergedMap = originalMap.mergeIn([keyPath], Map1, Map2, Map3, ...Map-n); – merges Maps at the location identified by keyPath. Does not merge nested Maps.
  • const mergedMap = originalMap.mergeDeepIn([keyPath], Map1, Map2, Map3, ...Map-n); – merges nested Maps deeply at the location identified by keyPath

Map.merge()

Merge two Maps together by adding the key/value pairs of the merging Maps to those of the Map being merged into. If the keys of any of the Maps are the same, the value of the duplicate key in the last Map to be merged in will be used.


// Merge 
const avengers = Immutable.Map({
    ironMan: 'Tony Stark',
    captainAmerica: 'Steve Rogers'
});

const mergingAvengers = Immutable.Map({
   blackWidow: 'Natasha Romanova',
   theHulk: 'Bruce Banner'
});

const mergedAvengers = avengers.merge(mergingAvengers);

// Output:
mergedAvengers;


mergeWith()

Merges two or more Maps together, but lets you control which value to use if there are any conflicts. Use it as follows:
const mergedMap = originalMap.Map((originalMapValue, mergedMapValue, key) => { /* conflict resolution */ }, mergedMap);

In the example below, the two Maps will be merged as normal, unless:

  • the merging Map’s value is undefined
  • the key is ‘ironMan’. His value must never be changed. He is immutable!

// Merge two Maps using mergeWith
const avengers = Immutable.Map({
  ironMan: 'Tony Stark',
  captainAmerica: undefined,
  blackWidow: 'Natasha Romanova',
});

const mergingAvengers = Immutable.Map({
  theHulk: 'Bruce Banner',
  blackWidow: undefined,
  ironMan: 'imposter!',
  captainAmerica: 'Steve Rogers',
});

const mergedAvengers = avengers.mergeWith((prev, next, key) => {
  // If mergingMap's value is undefined, return the originalMap's value
  if(!next) {
    return prev;
  }
  // If the key = 'ironMan', then use the originalMap's value
  if(key==='ironMan') {
    return prev;
  }
  // otherwise, use the mergingMap's value
  return next;
}, mergingAvengers);

// Output:
mergedAvengers;

mergeDeep()

mergeDeep() merges two or more Maps together, er, deeply (again, the clue’s in the title!). With standard merge(), nested Maps are not merged together – only the keys in the top-level Map are merged. With mergeDeep(), all nested Maps are merged recursively, regardless of their depth in the nesting hierarchy.

To see this in action, the example below shows mergeDeep() merging two Avengers together. Try changing the mergeDeep function to merge and see what happens.


// Merge two Maps using mergeDeep
const ironMan = Immutable.fromJS({
  heroes: {
    ironMan: {
      name: 'Tony Stark'
    },
    captainAmerica: {
      name: 'Steve Rogers'
    }
  }
});

const mergingMan = Immutable.fromJS({
  heroes: {
    ironMan: {
      partner: 'Pepper Potts'
    }
  }
});

const mergedMan = ironMan.mergeDeep(mergingMan);

// Output:
mergedMan;


mergeDeepWith()

mergeDeepWith() deeply merges two or more Maps together (including nested Maps), and lets you control which value to keep should there be duplicate keys in the Maps being merged.


// Merge two Maps using mergeDeepWith
const avengers = Immutable.fromJS({
  heroes: {
    ironMan: {
      name: 'Tony Stark'
    },
    captainAmerica: {
      name: 'Steve Rogers'
    }
  }
});

const mergingAvengers = Immutable.fromJS({
  heroes: {
    ironMan: {
       name: 'Tony Starkless',
       partner: 'Pepper Potts'
    },
    captainAmerica: {
      name: 'Chris Evans'
    }
  }
});

const mergedAvengers = avengers.mergeDeepWith((prev, next, key) => {
  // If the key = 'name', then use the originalMap's value
  if(key==='ironMan') {
    return prev;
  }
  // otherwise, use the mergingMap's value
  return next;
}, mergingAvengers);


// Output:
mergedAvengers;

Again, try changing mergeDeepWith with mergeWith and see what happens.


mergeIn()

Merges two or more Maps together at a specific point in a nested Map. Use it as follows:

const mergedMap = originalMap.mergeIn([keyPath], Map1, Map2, Map3, ...Map-n);


// Merge two Maps using mergeIn
const avengers = Immutable.fromJS({
  heroes: {
    ironMan: {
      name: 'Tony Stark'
    },
    captainAmerica: {
      name: 'Steve Rogers'
    }
  }
});

const mergingAvengers = Immutable.fromJS({
      partner: {
        realName: 'Pepper Potts',
        heroName: 'hera'
      }
});

const mergedAvengers = avengers.mergeIn(['heroes', 'ironMan'], mergingAvengers);

// Output:
mergedAvengers;


mergeDeepIn()

Merges two or more nested Maps together at a specific point in a nested Map. Use it as follows:

const mergedMap = originalMap.mergeDeepIn([keyPath], Map1, Map2, Map3, ...Map-n);

This is subtly different from mergeIn – indeed, it’s so subtle, I ended up looking through the Immutable source code looking for any differences!

They are there though. Change the following example from mergeDeepIn to mergeIn and see what happens.


// Merge two Maps using mergeDeepIn
const avengers = Immutable.fromJS({
  heroes: {
    type: {
       human: {
          ironMan: {
            name: 'Tony Stark'
          },
          captainAmerica: {
		     name: 'Steve Rogers'
          }
       },
      god: {
        thor : {
          name: 'Thor'
        }
      }
    },
  }
});

const mergingAvengers = Immutable.fromJS({
  human :{      
     blackWidow: {
        name: 'Natasha Romanova'
     }
  }
});

const mergedAvengers = avengers.mergeDeepIn(['heroes', 'type'], mergingAvengers);

// Output:
mergedAvengers;

There are no comments.

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>