Storms786
Storms786

Reputation: 466

Merging JSON properties for two arrays of JSON objects (using ramda)

Consider that I have two arrays as follows:

let a1 = [{id:1, name:'jon'}, {id:2, name:'adam'}]
let a2 = [{id:1, age:42}, {id:2, age:13}]

I want to merge the two arrays so the JSON properties get combined into one array; i.e. this is what I want to end up with:

[{ id: 1, name: 'jon', age: 42 },{ id: 2, name: 'adam', age: 13 }]

Using Ramda I can do the following which gives me close to what I want, but annoyingly it's not in an array - it's all JSON

R.mergeDeepLeft(a1, a2)
{ '0': { id: 1, name: 'yasin', age: 42 },
  '1': { id: 2, name: 'adam', age: 13 } }

Upvotes: 0

Views: 482

Answers (5)

Anton Bks
Anton Bks

Reputation: 492

Try this:

let a1 = [{id:1, name:'jon'}, {id:2, name:'adam'}]
let a2 = [{age:13, id:2}, {id:1, age:42}]

const fn = R.pipe(
   R.map(R.indexBy(R.prop('id'))),
   R.reduce(R.mergeWith(R.mergeDeepLeft), {}),
   R.values
)
    
let newArray1 = fn([a1, a2]);
let newArray2 = fn([a2, a1]);
    
console.log(newArray1);
console.log(newArray2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

Upvotes: 1

Niklv
Niklv

Reputation: 136

You can use R.values to convert to array, like this:

let a1 = [{id:1, name:'jon'}, {id:2, name:'adam'}]
let a2 = [{id:1, age:42}, {id:2, age:13}]

R.values(R.mergeWith(R.mergeLeft, a1, a2));

If you have unordered arrays, you can do this:

let a1 = [{id:1, name:'jon'}, {id:2, name:'adam'}]
let a2 = [{id:2, age:13}, {id:1, age:42}]

R.values(R.mergeWith(
  R.mergeLeft, 
  R.indexBy(R.prop('id'), a1), 
  R.indexBy(R.prop('id'), a2)
));

Upvotes: 1

Nuthan Kumar
Nuthan Kumar

Reputation: 493

let concatValues = (k, l, r) =>  r
R.mergeDeepWithKey(concatValues,a1,a2)

will produce this

{"0": {"age": 42, "id": 1, "name": "jon"}, "1": {"age": 13, "id": 2, "name": "adam"}}

it's not exact output but you can start with this

Upvotes: -1

customcommander
customcommander

Reputation: 18901

I'd do this:

  1. concat a1 and a2 together. (They don't need to be kept apart)
  2. group objects by id and merge those that share the same id.
  3. finally get all merged objects out.

const res =
  pipe(
    concat,
    reduceBy(mergeLeft, {}, prop('id')),
    values);

console.log(

  res(a1, a2)

);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>
const {pipe, concat, reduceBy, mergeLeft, values, prop} = R;
const a1 = [{id:1, name:'jon'}, {id:2, name:'adam'}];
const a2 = [{id:1, age:42}, {id:2, age:13}];
</script>

Upvotes: 4

Jbluehdorn
Jbluehdorn

Reputation: 475

Perhaps not the most elegant nor extensible solution but I'd use some mapping and the spread operator:

let a1 = [{id:1, name:'jon'}, {id:2, name:'adam'}]
let a2 = [{id:1, age:42}, {id:2, age:13}]
let a3 = a1.map(item => {
    return {...item, ...a2.find(item2 => item2.id === item.id)}
})

Here's a working Fiddle for it https://jsfiddle.net/gshfo7pm/

Upvotes: 2

Related Questions