Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ramda.js Combine two array of objects that share the same property ID

I have these two array of objects

todos: [
    {
      id: 1,
      name: 'customerReport',
      label: 'Report send to customer'
    },
    {
      id: 2,
      name: 'handover',
      label: 'Handover (in CRM)'
    },
  ]

And:

todosMoreDetails: [
          {
            id: 1,
            checked: false,
            link: {
              type: 'url',
              content: 'http://something.com'
            },
            notes: []
          },
          {
            id: 2,
            checked: false,
            link: {
              type: 'url',
              content: 'http://something.com'
            },
            notes: []
          }
        ]

So that the final array of objects will be a combination of the two, based on the object ID, like below:

FinalTodos: [
          {
            id: 1,
            checked: false,
            link: {
              type: 'url',
              content: 'http://something.com'
            },
            notes: [],
            name: 'customerReport',
            label: 'Report send to customer'
          },
          {
            id: 2,
            checked: false,
            link: {
              type: 'url',
              content: 'http://something.com'
            },
            notes: [],
            name: 'handover',
            label: 'Handover (in CRM)'
          }
        ]

I tried with merge mergeAll and mergeWithKey but I am probably missing something

like image 386
Anonymous Avatar asked Mar 09 '17 14:03

Anonymous


1 Answers

You can achieve this with an intermediate groupBy:

Transform the todosMoreDetails array into an object keyed by todo property ID using groupBy:

var moreDetailsById = R.groupBy(R.prop('id'), todosMoreDetails);

moreDetailsById is an object where the key is id, and the value is an array of todos. If the id is unique, this will be a singleton array:

{
      1: [{
        id: 1,
        checked: false,
        link: {
          type: 'url',
          content: 'http://something.com'
        },
        notes: []
      }]
}

Now transform the todos array by merging each todo to it's details you retrieve from the grouped view:

var finalTodos = R.map(todo => R.merge(todo, moreDetailsById[todo.id][0]), todos);

An alternate more detailed way:

function mergeTodo(todo) {
   var details = moreDetailsById[todo.id][0]; // this is not null safe
   var finalTodo = R.merge(todo, details);
   return finalTodo;
}

var moreDetailsById = R.groupBy(R.prop('id'), todosMoreDetails);
var finalTodos = todos.map(mergeTodo);
like image 74
J O Avatar answered Sep 23 '22 01:09

J O