0

I want to merge these 2 arrays by ID and sorted the merged result array by ID desc.

  • Don't want to use any external lib like Lodash or Underscore

  • Prefere to use ES6 with a less lines of code as possible

.

const array1 = [
  {id: "14",  text: "Notice 14"},
  {id: "13",  text: "Notice 13"},
  {id: "12",  text: "Notice 12"},
  {id: "11",  text: "Notice 11"},
  {id: "10",  text: "Notice 10"},
]

const array2 = [ 
  {id: "11",  text: "Notice 11a"},
  {id: "14",  text: "Notice 14a"},
  {id: "12",  text: "Notice 12"},
  {id: "15",  text: "Notice 15"},
]

I want a merged array by ID and order by ID desc:

[
{id: "15",  text: "Notice 15"}
{id: "14",  text: "Notice 14a"}
{id: "13",  text: "Notice 13"}
{id: "12",  text: "Notice 12"}
{id: "11",  text: "Notice 11a"}
{id: "10",  text: "Notice 10"}
]
Marek Lipka
  • 50,622
  • 7
  • 87
  • 91
Joel
  • 974
  • 2
  • 10
  • 18
  • Possible duplicate of [Merge two array of objects based on a key](https://stackoverflow.com/questions/46849286/merge-two-array-of-objects-based-on-a-key) – Heretic Monkey Oct 09 '18 at 16:58
  • Sorry but isn't the same answer. I need merge and ORDER array of objects. – Joel Oct 09 '18 at 17:29
  • There are many, many questions about ordering arrays of objects; [Sort array of objects by string property value](https://stackoverflow.com/q/1129216) is one of them. – Heretic Monkey Oct 09 '18 at 17:30

4 Answers4

3

You could try something like:

Object
  .values([...array1, ...array2].reduce((acc, item) => ({ ...acc, [item.id]: item }), {}))
  .sort((a, b) => (b.id - a.id))
n1stre
  • 5,856
  • 4
  • 20
  • 41
2

Here's a solution with filter, concat, and sort (assuming that values in array2 override those in array1).

const array1 = [
  {id: "14",  text: "Notice 14"},
  {id: "13",  text: "Notice 13"},
  {id: "12",  text: "Notice 12"},
  {id: "11",  text: "Notice 11"},
  {id: "10",  text: "Notice 10"}
];

const array2 = [ 
  {id: "11",  text: "Notice 11a"},
  {id: "14",  text: "Notice 14a"},
  {id: "12",  text: "Notice 12"},
  {id: "15",  text: "Notice 15"}
];

const merged = array1
                .filter(e => array2.find(a2e => a2e.id === e.id) === undefined)
                .concat(array2)
                .sort((a, b) => parseInt(b.id) - parseInt(a.id));
console.log(merged);

The idea is to filter elements in array1 that are not in array2 and then concatenate them with all elements in array2 since that is the preferred array.

Note that this is not very efficient since we're interested in the least amount of code. We can improve performance by creating a set of id elements of array2 so that we can replace the check array2.find(a2e => a2e.id === e.id) === undefined with a faster O(1) check.

slider
  • 12,810
  • 1
  • 26
  • 42
0

Generic Solution for any number of arrays:

function mergeArrays(...arrays){
    let obj = {};
    [].concat(...arrays).forEach(item => {
      obj[item.id] = item
    })
    
    return Object.values(obj)
}

Breaking it down:

Considering you want only unique ids and the elements of second array are preferred in case of conflicts, this is how it can be done:

function createObject(arr){
   let obj = {};
   arr.forEach(item => obj[item.id] = item )
   return obj;
}

function getArray(obj) {
  return Object.values(obj)
}


let mergedArray = getArray({
   ...createObject(array1), 
   ...createObject(array2) 
})

To explain it a bit further:

1) You convert both arrays into an object, where ids acts as the keys

2) when two objects are merged, conflicts are resolved by keeping the value of the second object

3) Finally, you reverse engineer the first step to get the final array back from the object format.

Anish K.
  • 2,402
  • 3
  • 19
  • 25
0

Using modern Javascript, you can use a Map object to solve this problem.

const array1 = [
    {id: "14",  text: "Notice 14"},
    {id: "13",  text: "Notice 13"},
    {id: "12",  text: "Notice 12"},
    {id: "11",  text: "Notice 11"},
    {id: "10",  text: "Notice 10"}
];

const array2 = [ 
    {id: "11",  text: "Notice 11a"},
    {id: "14",  text: "Notice 14a"},
    {id: "12",  text: "Notice 12"},
    {id: "15",  text: "Notice 15"}
];


function merge(arr1, arr2) {
    // Use a Map to map objects by Id
    const map = new Map();
    arr1.forEach(e => map.set(e.id, e));
    arr2.forEach(e => map.set(e.id, e));

    // Create an empty array and populate it with the map entries
    const result = [];
    map.forEach( (value, key, map) => result.push(value));

    // Sort by ID desc
    result.sort((a, b) => a.id < b.id);
    return result;
}

console.log(merge(array1, array2));

This prints:

[ { id: '15', text: 'Notice 15' },
  { id: '14', text: 'Notice 14a' },
  { id: '13', text: 'Notice 13' },
  { id: '12', text: 'Notice 12' },
  { id: '11', text: 'Notice 11a' },
  { id: '10', text: 'Notice 10' } ]
HugoTeixeira
  • 4,674
  • 3
  • 22
  • 32