6

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

2 Answers 2

12

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);
2
  • It works!! But I have no idea why. Could you give a brief explanation? That would be great
    – Anonymous
    Commented Mar 9, 2017 at 15:08
  • 1
    added some more details to my suggestion
    – J O
    Commented Mar 9, 2017 at 15:30
-4

I guess merge is only used for arrays. Have a search for object "extend". Maybe storing the todo details not in seperate objects is the better solution.

Using underscore:

var result = [];
var entry = {};
_.each(todos, function(todo) {
    _.each(todosMoreDetails, function(detail) {
        if (todo.id == detail.id) {
            entry = _.extend(todo, detail);
            result.push(entry);
        }
    }
});
return result;
1
  • OP tagged it with ramdajs and it is in the title.
    – Jared
    Commented Dec 30, 2018 at 6:15

Not the answer you're looking for? Browse other questions tagged or ask your own question.