'Merge multiple object arrays and removing duplicates based on optional property

Say if there are arrays like:

const arr1 = [
   { "id": "1", "type": "sales" },
   { "id": "2", "type": "finance" }
]

const arr2 = [
   { "type": "sales" },
   { "id": "2", "type": "finance" }
]

const arr3 = [
   { "id": "1", "type": "sales" },
   { "type": "sales" },
   { "type": "finance" }
]

As you can see, id is optional. I need to merge arrays in such way that uniqueness should be based on id if present, else entire rest of the object. ex. here merged array would be:

[ 
  { "id": "1", "type": "sales" }, 
  { "type": "sales" }, 
  { "id": "2", "type": "finance" }, 
  { "type": "finance" } 
]

loadash has .unionBy but optional uniqueness doesn't work.

const result = _.unionBy(arr1, arr2, arr3, 'id')

Probably I have to iterate through each, but I was wondering if there is any simpler alternative for this.



Solution 1:[1]

Instead of _.unionBy you can use _.unionWith which accepts a custom comparator. The logic for comparison is:

  1. Compare by ID if both items have an ID.
  2. Compare by type if both items do not have an ID.
  3. Consider them different if one has an ID the other not.

const arr1 = [
   { "id": "1", "type": "sales" },
   { "id": "2", "type": "finance" }
]

const arr2 = [
   { "type": "sales" },
   { "id": "2", "type": "finance" }
]

const arr3 = [
   { "id": "1", "type": "sales" },
   { "type": "sales" },
   { "type": "finance" }
]

const result = _.unionWith(arr1, arr2, arr3, (item1, item2) => {
  const item1HasId = _.has(item1, "id");
  const item2HasId = _.has(item2, "id");
  
  if (item1HasId && item2HasId) //if both have ID...
    return item1.id === item2.id; // ...compare by ID
    
  if (!item1HasId && !item2HasId) //if neither has ID...
    return item1.type === item2.type; // ...compare by type
    
  return false; // otherwise not equal
});

console.log(result);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 VLAZ