Merge two arrays with deeply nested key with Ramda

Multi tool use
Merge two arrays with deeply nested key with Ramda
I've recently started using Ramda to work with responses from JSONAPI. I am a bit confused as to how I should be merging two objects by a deeply nested key.
For example:
Take these two sets of data,
const users = [
{ id: 1,
attributes: {
firstName: "Bob",
lastName: "Lee"
},
relationships: {
phone: {
data: {
id: 2,
type: "phone"
}
}
},
type: "users"
},
{ id: 2,
attributes: {
firstName: "Kevin",
lastName: "Smith"
},
relationships: {
phone: {
data: {
id: 5,
type: "phone"
}
}
},
type: "users"
},
];
const phones= [
{ id: 2,
attributes: {
phoneNumber: "123-345-6789"
},
type: "phones"
},
{ id: 5,
attributes: {
phoneNumber: "987-654-4321"
},
type: "phones"
},
];
What I want to create is a new array with the related phone added to the user array with a new key holding all related objects, like this:
const newUser =
[
{ id: 1,
attributes: {
firstName: "Bob",
lastName: "Lee"
},
relationships: {
phone: {
data: {
id: 2,
type: "phones"
}
}
},
included: {
phoneNumber: "123-345-6789"
}
},
{ id: 2,
attributes: {
firstName: "Kevin",
lastName: "Smith"
},
relationships: {
phone: {
data: {
id: 5,
type: "phones"
}
}
},
type: "users",
included: {
phoneNumber: "987-654-4321"
}
}
]
I've tried multiple methods like map, pick, and join but the objects just don't seem to want to merge the way I want them to. The following code puts both of the objects into the same array, but I can't seem to wrap my head around where to go next.
const data = R.pipe(
R.juxt([
R.pipe(R.path(['users'])),
R.pipe(R.path(['phones']))
]),
)
}),
{}
Also in
type: phone
, is phone defined elsewhere, or should this just be a string?– Scott Sauyet
Jul 2 at 19:49
type: phone
Actually it is in fact an object.. but I can turn it into an array with R.values, right? Also phone should be a string, sorry! I will edit that
– davidhong
Jul 2 at 19:56
Well, your sample code doesn't have any keys...
– Scott Sauyet
Jul 2 at 20:19
I changed the sets of data to arrays
– davidhong
Jul 2 at 20:35
1 Answer
1
Here's my first approach:
const {map, path, find, propEq, assoc} = R
const addPhones = (phones, users) => map(user => {
const phoneId = path(['relationships', 'phone', 'data', 'id'], user)
const phone = find(propEq('id', phoneId), phones)
return phone
? assoc('included', phone.attributes, user)
: user
}, users)
const users = [{"attributes": {"firstName": "Bob", "lastName": "Lee"}, "id": 1, "relationships": {"phone": {"data": {"id": 2, "type": "phone"}}}, "type": "users"}, {"attributes": {"firstName": "Kevin", "lastName": "Smith"}, "id": 2, "relationships": {"phone": {"data": {"id": 5, "type": "phone"}}}, "type": "users"}, {"attributes": {"firstName": "Nancy", "lastName": "Johnson"}, "id": 3, "relationships": {"phone": {"data": {"id": 6, "type": "phone"}}}, "type": "users"}]
const phones= [{"attributes": {"phoneNumber": "123-345-6789"}, "id": 2, "type": "phones"}, {"attributes": {"phoneNumber": "987-654-4321"}, "id": 5, "type": "phones"}, {"attributes": {"phoneNumber": "212-867-5309"}, "id": 7, "type": "phones"}]
console.log(addPhones(phones, users))
//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js
This version deals appropriately with missing values in either list. If there is a user with no matching phone, the user is returned as-is, with no included
property. And if there is a phone with no matching user, it is simply ignored.
included
This makes the assumption that you can include the entire phone.attributes
object in your user. If you need to include only the phoneNumber
, it's only slightly more complex, replacing the obvious line with
phone.attributes
phoneNumber
? assocPath(['included', 'phoneNumber'], phone.attributes.phoneNumber, user)
thanks, i will look into this approach. is it possible to do all of this in one pipe?
– davidhong
Jul 3 at 17:42
I'm not sure what you mean by "all in one pipe". If you mean a point-free version of it, then I'd say it would not be pretty.
– Scott Sauyet
Jul 6 at 0:27
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Are your actual object arrays? Your samples use
{}
for the outer brackets, but no keys. Should they be?
– Scott Sauyet
Jul 2 at 19:42