Map array inside an object - javascript

I've the following complex JSON object that has got array and array inside an array. How can parse those arrays and create an object array for each element in the array. I'm using lodash library in my project, just in case if there are any functions available.
{
studentId: 123
name: XYZ
phone: 34234234
gender: M
subjects: [{
studentId: 123
subjectName: Math
scores:50
assignments:[
{
type: Internal,
submitted: yes,
status: failed
},
{
type: External,
submitted: yes,
status: passed
}]
},
{
studentId: 123
subjectName: Science
score: 20
assignments:[
{
type: Internal,
submitted: yes,
status: passed
},
{
type: External,
submitted: yes,
status: failed
}]
}]
}
Expecting:
[{
studentId:123,
name: XYZ
phone: 34234234
gender: M,
subjectName: Math
scores:50
assignments:[
{
type: Internal,
submitted: yes,
status: failed
},
{
type: External,
submitted: yes,
status: passed
}]
},
{
studentId:123,
name: XYZ
phone: 34234234
gender: M,
subjectName: science
scores:20
assignments:[
{
type: Internal,
submitted: yes,
status: failed
},
{
type: External,
submitted: yes,
status: passed
}]
}
]

You can use omit to get the details of the student without the subjects array, use these details to transform each item in the subjects array using defaults through map.
var details = _.omit(data, 'subjects');
var result = _.map(data.subjects, function(subject) {
return _.defaults({}, details, subject);
});
var data = {
studentId: '123',
name: 'XYZ',
phone: '34234234',
gender: 'M',
subjects: [{
studentId: '123',
subjectName: 'Math',
scores: 50,
assignments: [{
type: 'Internal',
submitted: 'yes',
status: 'failed'
},
{
type: 'External',
submitted: 'yes',
status: 'passed'
}
]
},
{
studentId: '123',
subjectName: 'Science',
score: 20,
assignments: [{
type: 'Internal',
submitted: 'yes',
status: 'passed'
},
{
type: 'External',
submitted: 'yes',
status: 'failed'
}
]
}
]
};
var details = _.omit(data, 'subjects');
var result = _.map(data.subjects, function(subject) {
return _.defaults({}, details, subject);
});
console.log(result);
body > div { min-height: 100%; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

I encourage you to use Normalizr package. It's very useful and takes all care about your collections even if they're nested.

Related

Remap an array to have an object above each entry in javascript

I have a prisma query that returns users on a pivot table CommunityMember. The pivot table associates to the table User. As a result, my queries into the User table do not place the object user on top of the replies. I have a lot of functions designed to run with the user object on top so I am trying to figure out how to map user into my returns so the functions can run correctly. I've tried a lot of combinations of map and have had no luck. Do you all have any ideas?
Here is my prisma query:
members = await prisma.user.findMany({
select: {
id: true,
username: true,
name: true,
bio: true,
avatar: true,
},
skip: 10 * Number(page),
take: 10,
});
It gives a result like
members:
[{id: 2, username: 'man}, {id: 3, username: 'dan'}]
I want it to look like: members:
members:
[{user: {id: 2, username: 'man'}}, {user: {id: 3. username: 'dan'}}]
If I run members[0].user I should get the data inside. It seems like a simple map function, but I have not been able to get it to work.
Another example of what I get, but do not want.
members: [
{
id: 2,
username: 'man',
name: 'A Man',
bio: 'A man.',
avatar: [Object]
},
{
id: 3,
username: 'dude',
name: 'Dude',
bio: "Dude is a #1 developer.",
avatar: [Object]
},
This is what I want.
members: [
{
//Notice the user object on top of each entry
user: {
id: 2,
username: 'man',
name: 'A Man',
bio: 'Man.',
avatar: [Object]
}
},
{
user: {
id: 3,
username: 'dude',
name: 'Dude',
bio: "Dudes a #1 developer.",
avatar: [Object]
}
},
]
Not sure I got the whole picture but wouldn't this do?
const members = [
{
id: 2,
username: 'man',
name: 'A Man',
bio: 'A man.',
avatar: {}
},
{
id: 3,
username: 'dude',
name: 'Dude',
bio: "Dude is a #1 developer.",
avatar: {}
}
].map(member => ({user: member}))
if your object looks like:
obj = {members: [{...}, ..]}
then an Array.map will solve the problem:
const userMembers = obj.members.map((member) => ({user: member});
obj.members = userMembers;

What is it a good way in javascript to merge two array of objects when there is a match with a specific key/value

In a project I'm working on, I need to merge 2 arrays of objects and as a result one new array of objects containing the merged key/values where two Ids match.
To give an example I created the following snippet but is not fully correct on what I want to achieve. More details after the snippet
const users = [{
id: 'Ae7uWu7LjwoEgVqzFU5xc',
firstName: 'Carl',
lastName: 'Jones'
},
{
id: 't2wzj8dh4r-qw1_SW-IOE',
firstName: 'Chloe',
lastName: 'Kearney'
},
{
id: '50Zwvw37OejbQBG7csZWJ',
firstName: 'Gemma',
lastName: 'Sloan'
},
{
id: 'NpcXdEKqfzhVCZOJ1dKuw',
firstName: 'Dario',
lastName: 'Angelini'
},
{
id: 'e95ZG9IfV442HdJp-CaBL',
firstName: 'Mindy',
lastName: 'Schreiber'
},
{
id: 'eAMv8AbynYRkdBPE5Scm2',
firstName: 'Xdax',
lastName: 'Rufq'
},
{
id: 'egMXnFvoMM7f4in3Se4Ui',
firstName: 'Mtajx',
lastName: 'Plde'
},
{
id: '6kbPT-HC5-szACuJ85I6r',
firstName: 'Zsofi',
lastName: 'Toke'
}
]
const comments = [{
content: 'Patient follow up call scheduled for 11Nov2021 at 8am',
stage: 'AT_CALLCENTER',
userId: 't2wzj8dh4r-qw1_SW-IOE',
createdAt: '2021-10-29T11:41:11.780Z'
},
{
content: 'Patient confirmed GP referral on [date]',
stage: 'AT_CALLCENTER',
userId: 't2wzj8dh4r-qw1_SW-IOE',
createdAt: '2021-10-29T11:41:42.237Z'
},
{
content: 'Candidate called on [date] and visit scheduled for [date] ',
stage: 'AT_SITE',
userId: 't2wzj8dh4r-qw1_SW-IOE',
createdAt: '2021-10-29T11:43:42.140Z'
},
{
content: 'Candidate test result was positive for Pompe disease on [date]',
stage: 'AT_SITE',
userId: 't2wzj8dh4r-qw1_SW-IOE',
createdAt: '2021-10-29T11:45:21.716Z'
}
]
const result = users.map(t1 => ({
...t1,
content: comments.filter(t2 => t2.userId === t1.id).map(t1 => t1.content),
created: comments.filter(t2 => t2.userId === t1.id).map(t1 => t1.createdAt),
}));
console.log(result)
The result I was able to get from that try was an array of objects but the comments are represented as an array inside the user object itself as for the createdAt
this is an example of what I'm getting now
[{
"id": "t2wzj8dh4r-qw1_SW-IOE",
"firstName": "Chloe",
"lastName": "Kearney",
"content": [
"Patient follow up call scheduled for 11Nov2021 at 8am",
"Patient confirmed GP referral on [date]",
"Candidate called on [date] and visit scheduled for [date] ",
"Candidate test result was positive for Pompe disease on [date]"
],
"created": [
"2021-10-29T11:41:11.780Z",
"2021-10-29T11:41:42.237Z",
"2021-10-29T11:43:42.140Z",
"2021-10-29T11:45:21.716Z"
]
},]
What I would like to get is the way around, I mean I want the comments to include the
firstName and lastName of the user when the comments.userId is equal to the users.id
Example of the goal I want to achieve
consider the 2 objects below
comments = [{
content: 'Patient follow up call scheduled for 11Nov2021 at 8am',
stage: 'AT_CALLCENTER',
userId: 't2wzj8dh4r-qw1_SW-IOE',
createdAt: '2021-10-29T11:41:11.780Z'
},
{
content: 'Patient confirmed GP referral on [date]',
stage: 'AT_CALLCENTER',
userId: 't2wzj8dh4r-qw1_SW-IOE',
createdAt: '2021-10-29T11:41:42.237Z'
}, { ...some other comments...}]
users = [
{
id: 't2wzj8dh4r-qw1_SW-IOE',
firstName: 'Chloe',
lastName: 'Kearney'
},
{ ...some other users... }]
The result I'm seeking after the 2 objects are merged is as follows
res = [
{
firstName: 'Chloe',
lastName: 'Kearney',
content: 'Patient follow up call scheduled for 11Nov2021 at 8am',
stage: 'AT_CALLCENTER',
userId: 't2wzj8dh4r-qw1_SW-IOE',
createdAt: '2021-10-29T11:41:11.780Z'
},
{
firstName: 'Chloe',
lastName: 'Kearney',
content: 'Patient confirmed GP referral on [date]',
stage: 'AT_CALLCENTER',
userId: 't2wzj8dh4r-qw1_SW-IOE',
createdAt: '2021-10-29T11:41:42.237Z'
}
]
As above I'm adding the first and last name of the user with the comments where there is an Ids match, so they are together after the merging.
I'm looking to understand a good way of doing this
const comments = [{
content: 'Patient follow up call scheduled for 11Nov2021 at 8am',
stage: 'AT_CALLCENTER',
userId: 't2wzj8dh4r-qw1_SW-IOE',
createdAt: '2021-10-29T11:41:11.780Z'
},{
content: 'Patient confirmed GP referral on [date]',
stage: 'AT_CALLCENTER',
userId: 't2wzj8dh4r-qw1_SW-IOE',
createdAt: '2021-10-29T11:41:42.237Z'
}];
const users = [{
id: 't2wzj8dh4r-qw1_SW-IOE',
firstName: 'Chloe',
lastName: 'Kearney'
}];
console.log(
comments.map(comment => {
const {id, ...user} = users.find(({id}) => id===comment.userId);
return ({...user, ...comment});
}));

Remove nested array from an object

What is the best way to convert
const mockResults = [
[{ user: { firstName: '1', lastName: '1' }, status: 'WRONG' }],
[{ user: { firstName: '2',lastName: '2' }, status: 'WRONG' }],
[{ user: { firstName: '3',lastName: '3' }, status: 'CORRECT' }]
];
to
const mockResults = [
{ user: { firstName: '1', lastName: '1' }, status: 'WRONG' },
{ user: { firstName: '2',lastName: '2' }, status: 'WRONG' },
{ user: { firstName: '3',lastName: '3' }, status: 'CORRECT' }
];
The whole task is to transform mockResults to requiredFormat, that's why I need to remove nested arrays:
const requiredFormat = [
{
status: 'WRONG',
data: [{ user: {firstName: '1', lastName: '1'}}, { user: {firstName: '2', lastName: '2'}}],
},
{
status: 'CORRECT',
data: [{ user: {firstName: '3', lastName: '3'}}],
},
];
Here's what I tried so far:
https://jsfiddle.net/9uLje3sg/
Thanks!
You can use flat method from Array javascript object. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat
If you want to change the source of data and change the shape of it, using map and reduce methods can help you.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
In your precise example reduce would fit as you are creating a new object grouping per status property.
const mockResults = [
[{ user: { firstName: '1', lastName: '1' }, status: 'WRONG' }],
[{ user: { firstName: '2',lastName: '2' }, status: 'WRONG' }],
[{ user: { firstName: '3',lastName: '3' }, status: 'CORRECT' }]
];
const flattedAndReduced = mockResults.flat().reduce( (acc, curr)=>{
const statusIndex = { 'WRONG' : 0, 'CORRECT': 1 };
acc[statusIndex[curr.status]].data.push({ user: curr.user} );
return acc;
}, [
{
status: 'WRONG',
data: [],
},
{
status: 'CORRECT',
data: [],
}
]
);
console.log(flattedAndReduced);
Use the function map as follow which returns an array with the desired objects.
let result = mockResults.map(([user]) => user);
That approach is assuming there is only one index per array from the original array.
According to the approach for requiredFormat
You can use the function reduce for grouping and the function Object.values for getting the desired output.
const mockResults = [
[{ user: { firstName: '1', lastName: '1' }, status: 'WRONG' }],
[{ user: { firstName: '2',lastName: '2' }, status: 'WRONG' }],
[{ user: { firstName: '3',lastName: '3' }, status: 'CORRECT' }]
];
let requiredFormat = Object.values(mockResults.reduce((a, [{user, status}]) => {
(a[status] || (a[status] = {data: [], status})).data.push(user);
return a;
}, Object.create(null)));
console.log(requiredFormat);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Simply use Array.prototype.map() to return the object from first index.
Please Note: variable declared with const can not be modified, use *let instead.
let mockResults = [
[{ user: { firstName: '1', lastName: '1' }, status: 'WRONG' }],
[{ user: { firstName: '2',lastName: '2' }, status: 'WRONG' }],
[{ user: { firstName: '3',lastName: '3' }, status: 'CORRECT' }]
];
mockResults = mockResults.map(i => i[0]);
console.log(mockResults);
const mockResults = [
[{ user: { firstName: '1', lastName: '1' }, status: 'WRONG' }],
[{ user: { firstName: '2',lastName: '2' }, status: 'WRONG' }],
[{ user: { firstName: '3',lastName: '3' }, status: 'CORRECT' }]
];
const requiredFormat = [
{status: 'WRONG', data: []},
{status: 'CORRECT', data: []},
];
for(let [{user,status}] of mockResults) {
requiredFormat[ status==="WRONG" ? 0 : 1].data.push({user});
}
console.log(requiredFormat);

Firebase firestore set array of objects to document

I need to set an array for objects to firestore but only the first index of urls is getting stored. Any help in the right direction would be helpful thanks.
Code:
const object = [
{
user: 'mike',
userName: 'Mike nick',
Urls:[
{comment: "BBBBB", imageUrl: "url1"},
{comment: "BBBJvuyiu", imageUrl: "url2"},
{comment: "AAAAA", imageUrl: "url3"},
],
date: 'March 20th'
}
]
firestoreRef
.collection('users')
.doc(userId)
.collection('images')
.doc('customers')
.collection('customerExperience')
.doc(userId)
.set(object, { merge: true })
need this structure as user may continue to add more data:
it looks like this when i upload the object.
Your const object is actually an Array, when it should be an Object (that is not an Array).
The following should work:
const object = {
user: 'mike',
userName: 'Mike nick',
urls: [
{ comment: 'BBBBB', imageUrl: 'url1' },
{ comment: 'BBBJvuyiu', imageUrl: 'url2' },
{ comment: 'AAAAA', imageUrl: 'url3' }
],
date: 'March 20th'
};
Note the difference with your object:
const object = [
{
.....
}
]
UPDATE following your comment:
If you want to have it saved exactly the way you show in your updated question, do as follows. I am not sure however that this is the best way to save your data: as a matter of fact you are not creating an array but several fields of type "map" with the following names: 0, 1, etc.
One of the main (negative) side effect is that you will need to know all the fields names upfront in order to read them, while with a "genuine" Array field, you can loop over its values.
const object = {
0: {
user: 'mike1',
userName: 'Mike nick',
urls: [
{ comment: 'BBBBB', imageUrl: 'url1' },
{ comment: 'BBBJvuyiu', imageUrl: 'url2' },
{ comment: 'AAAAA', imageUrl: 'url3' }
],
date: 'March 20th'
},
1: {
user: 'mike2',
userName: 'Mike nick',
urls: [
{ comment: 'BBBBB', imageUrl: 'url1' },
{ comment: 'BBBJvuyiu', imageUrl: 'url2' },
{ comment: 'AAAAA', imageUrl: 'url3' }
],
date: 'March 20th'
}
};
From the Official Documentation, here's the sample code for the different data types:
let data = {
stringExample: 'Hello, World!',
booleanExample: true,
numberExample: 3.14159265,
dateExample: admin.firestore.Timestamp.fromDate(new Date('December 10, 1815')),
arrayExample: [5, true, 'hello'],
nullExample: null,
objectExample: {
a: 5,
b: true
}
};
You will need the following to create an object that contains an array of objects
let object = {
user: 'mike',
userName: 'Mike nick',
urls: {
[{comment: 'BBBBB', imageUrl: 'url1'},
{comment: 'BBBJvuyiu', imageUrl: 'url2'},
{comment: 'AAAAA', imageUrl: 'url3'}]
},
date: 'March 20th'
};
Let me know if this works for you.

Object manipulation javascript, add value of object to an array of object

An example will speak for itself :
Array of Object :
[{
userId: 'ab4e3870-287e-11e7-b5a1-abb6183e9866',
email: 'email1#hotmail.com'
},{
userId: 'ae149220-2883-11e7-bbf9-1fb134f2b4ad',
email: 'email2#hotmail.com'
}]
Object
{
'ab4e3870-287e-11e7-b5a1-abb6183e9866': { name: 'john', roles: 'detective'},
'ae149220-2883-11e7-bbf9-1fb134f2b4ad': { name: 'james', roles: 'plumber'},
}
The result i'd like would be :
[{
userId: 'ab4e3870-287e-11e7-b5a1-abb6183e9866',
email: 'email1#hotmail.com',
name: 'john',
roles: 'detective'
},{
userId: 'ae149220-2883-11e7-bbf9-1fb134f2b4ad',
email: 'email2#hotmail.com',
name: 'james',
roles: 'plumber'
}]
So basically, the value of the key that match the userId in Object is added to that object in the array.
Is there some simple way I don't see to do that? Without external libraries in ES6?
var data = [{
userId: 'ab4e3870-287e-11e7-b5a1-abb6183e9866',
email: 'email1#hotmail.com'
},{
userId: 'ae149220-2883-11e7-bbf9-1fb134f2b4ad',
email: 'email2#hotmail.com'
}]
var d = {
'ab4e3870-287e-11e7-b5a1-abb6183e9866': { name: 'john', roles: 'detective'},
'ae149220-2883-11e7-bbf9-1fb134f2b4ad': { name: 'james', roles: 'plumber'},
};
Using ES6 spread operator ...
data = data.map(function(item) {
return {...item, ...d[item.userId]}
});
ES5: By adding properties manually
data = data.map(function(item) {
item.name = d[item.userId].name;
item.roles = d[item.userId].roles;
return item;
});

Categories