How to use reduce to retrieve values from deep nested array objects - javascript

I'm trying to get a list of all users with the author.username property. So that means access posts author, comments author, and commentReplies author. I want an returned array with a list of usernames.
expected output
["blankman", "blankman2", "barnowl", "barnowl2", "blankman3"]
the wrong output
["blankman", "blankman2blankman3", "barnowl2"]
This is how im doing it but i think im doing it wrong. as its not dynamic
const arr = [{
"id": 5,
"title": "buttercup",
"postContent": "dsdsfsfsfsfsfs",
"likedByMe": false,
"likeCounts": 0,
"userId": 1,
"createdAt": "2020-08-17T03:41:16.749Z",
"updatedAt": "2020-08-17T03:41:16.749Z",
"author": {
"username": "blankman",
"gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
"bio": null
},
"Likes": [],
"Comments": [{
"id": 46,
"comment_body": "fsfsfsfsfsf",
"gifUrl": "",
"userId": 1,
"postId": 5,
"createdAt": "2020-08-18T04:46:08.946Z",
"updatedAt": "2020-08-18T04:46:08.946Z",
"commentReplies": [{
"id": 18,
"replyBody": "fsfsffsffsffsf",
"userId": 2,
"commentId": 46,
"postId": 5,
"createdAt": "2020-08-21T16:40:47.205Z",
"updatedAt": "2020-08-21T16:40:47.205Z",
"author": {
"username": "barnowl",
"gravatar": null,
"bio": null
}
}],
"author": {
"username": "blankman2",
"gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
"bio": null
}
},
{
"id": 47,
"comment_body": "fsfsfsfsfsf",
"gifUrl": "",
"userId": 1,
"postId": 5,
"createdAt": "2020-08-18T04:46:08.946Z",
"updatedAt": "2020-08-18T04:46:08.946Z",
"commentReplies": [{
"id": 18,
"replyBody": "fsfsffsffsffsf",
"userId": 2,
"commentId": 46,
"postId": 5,
"createdAt": "2020-08-21T16:40:47.205Z",
"updatedAt": "2020-08-21T16:40:47.205Z",
"author": {
"username": "barnowl2",
"gravatar": null,
"bio": null
}
}],
"author": {
"username": "blankman3",
"gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
"bio": null
}
},
],
"RePosts": [],
"RepostedByMe": false
}]
const findUsers = arr.reduce((acc, cv) => {
const users = [
...acc,
cv.author.username, // get first level author.username
cv.Comments.reduce((acc, cv) => acc.concat(cv.author.username), ""), // get comments author.username
cv.Comments.reduce((acc, cv) => cv.commentReplies.reduce((acc, cv) => acc.concat(cv.author.username), ""), "") // get comment replies author.username
]
return users
}, [])
console.log(findUsers)

You can do this iteratively or recursively:
const arr = [{
"id": 5,
"title": "buttercup",
"postContent": "dsdsfsfsfsfsfs",
"likedByMe": false,
"likeCounts": 0,
"userId": 1,
"createdAt": "2020-08-17T03:41:16.749Z",
"updatedAt": "2020-08-17T03:41:16.749Z",
"author": {
"username": "blankman",
"gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
"bio": null
},
"Likes": [],
"Comments": [
{
"id": 46,
"comment_body": "fsfsfsfsfsf",
"gifUrl": "",
"userId": 1,
"postId": 5,
"createdAt": "2020-08-18T04:46:08.946Z",
"updatedAt": "2020-08-18T04:46:08.946Z",
"commentReplies": [
{
"id": 18,
"replyBody": "fsfsffsffsffsf",
"userId": 2,
"commentId": 46,
"postId": 5,
"createdAt": "2020-08-21T16:40:47.205Z",
"updatedAt": "2020-08-21T16:40:47.205Z",
"author": {
"username": "barnowl",
"gravatar": null,
"bio": null
}
}
],
"author": {
"username": "blankman2",
"gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
"bio": null
}
},
{
"id": 47,
"comment_body": "fsfsfsfsfsf",
"gifUrl": "",
"userId": 1,
"postId": 5,
"createdAt": "2020-08-18T04:46:08.946Z",
"updatedAt": "2020-08-18T04:46:08.946Z",
"commentReplies": [
{
"id": 18,
"replyBody": "fsfsffsffsffsf",
"userId": 2,
"commentId": 46,
"postId": 5,
"createdAt": "2020-08-21T16:40:47.205Z",
"updatedAt": "2020-08-21T16:40:47.205Z",
"author": {
"username": "barnowl2",
"gravatar": null,
"bio": null
}
}
],
"author": {
"username": "blankman3",
"gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
"bio": null
}
},
],
"RePosts": [],
"RepostedByMe": false
}]
// No recursion
function getUsers(array) {
return array.flatMap(v => {
let comments = v.Comments;
return [v.author.username].concat(comments.flatMap(c => {
let replies = c.commentReplies;
return [c.author.username].concat(replies.flatMap(r => {
return r.author.username;
}));
}));
});
}
// Recursion
function recursGetUsers(array) {
if (!array) return [];
return array.flatMap(v => {
return [v.author.username]
.concat(recursGetUsers(v.Comments))
.concat(recursGetUsers(v.commentReplies));
});
}
console.log(getUsers(arr));
console.log(recursGetUsers(arr));

You can use several nested flatMap and map operations.
const arr = [{ "id": 5, "title": "buttercup", "postContent": "dsdsfsfsfsfsfs", "likedByMe": false, "likeCounts": 0, "userId": 1, "createdAt": "2020-08-17T03:41:16.749Z", "updatedAt": "2020-08-17T03:41:16.749Z", "author": { "username": "blankman", "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN", "bio": null }, "Likes": [], "Comments": [{ "id": 46, "comment_body": "fsfsfsfsfsf", "gifUrl": "", "userId": 1, "postId": 5, "createdAt": "2020-08-18T04:46:08.946Z", "updatedAt": "2020-08-18T04:46:08.946Z", "commentReplies": [{ "id": 18, "replyBody": "fsfsffsffsffsf", "userId": 2, "commentId": 46, "postId": 5, "createdAt": "2020-08-21T16:40:47.205Z", "updatedAt": "2020-08-21T16:40:47.205Z", "author": { "username": "barnowl", "gravatar": null, "bio": null } }], "author": { "username": "blankman2", "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN", "bio": null } }, { "id": 47, "comment_body": "fsfsfsfsfsf", "gifUrl": "", "userId": 1, "postId": 5, "createdAt": "2020-08-18T04:46:08.946Z", "updatedAt": "2020-08-18T04:46:08.946Z", "commentReplies": [{ "id": 18, "replyBody": "fsfsffsffsffsf", "userId": 2, "commentId": 46, "postId": 5, "createdAt": "2020-08-21T16:40:47.205Z", "updatedAt": "2020-08-21T16:40:47.205Z", "author": { "username": "barnowl2", "gravatar": null, "bio": null } }], "author": { "username": "blankman3", "gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN", "bio": null } }, ], "RePosts": [], "RepostedByMe": false }];
const res = arr.flatMap(x => [x.author.username].concat(x.Comments.flatMap(y => y.commentReplies.map(z => z.author.username).concat(y.author.username))));
console.log(res);

If your schema is settled down, your approach is a solution and almost reaching the goal (though recursion is another solution). the problem in your codes is uses Array.concat then return String. You should return one [] same as the most outer reduce.
Check below snippet:
const arr = [{
"id": 5,
"title": "buttercup",
"postContent": "dsdsfsfsfsfsfs",
"likedByMe": false,
"likeCounts": 0,
"userId": 1,
"createdAt": "2020-08-17T03:41:16.749Z",
"updatedAt": "2020-08-17T03:41:16.749Z",
"author": {
"username": "blankman",
"gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
"bio": null
},
"Likes": [],
"Comments": [
{
"id": 46,
"comment_body": "fsfsfsfsfsf",
"gifUrl": "",
"userId": 1,
"postId": 5,
"createdAt": "2020-08-18T04:46:08.946Z",
"updatedAt": "2020-08-18T04:46:08.946Z",
"commentReplies": [
{
"id": 18,
"replyBody": "fsfsffsffsffsf",
"userId": 2,
"commentId": 46,
"postId": 5,
"createdAt": "2020-08-21T16:40:47.205Z",
"updatedAt": "2020-08-21T16:40:47.205Z",
"author": {
"username": "barnowl",
"gravatar": null,
"bio": null
}
}
],
"author": {
"username": "blankman2",
"gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
"bio": null
}
},
{
"id": 47,
"comment_body": "fsfsfsfsfsf",
"gifUrl": "",
"userId": 1,
"postId": 5,
"createdAt": "2020-08-18T04:46:08.946Z",
"updatedAt": "2020-08-18T04:46:08.946Z",
"commentReplies": [
{
"id": 18,
"replyBody": "fsfsffsffsffsf",
"userId": 2,
"commentId": 46,
"postId": 5,
"createdAt": "2020-08-21T16:40:47.205Z",
"updatedAt": "2020-08-21T16:40:47.205Z",
"author": {
"username": "barnowl2",
"gravatar": null,
"bio": null
}
}
],
"author": {
"username": "blankman3",
"gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
"bio": null
}
},
],
"RePosts": [],
"RepostedByMe": false
}]
const findUsers = arr.reduce((acc, cv) => {
const users = [
...acc,
cv.author.username, // get first level author.username
...cv.Comments.reduce((acc, cv) => [...acc, cv.author.username], []), // get comments author.username
...cv.Comments.reduce((acc, cv) => [...acc, ...cv.commentReplies.reduce((acc, cv) => [...acc, cv.author.username], [])], []) // get comment replies author.username
]
return users
}, [])
console.log(findUsers)

This is the schema of your object:
author.username
Comments[i].author.username
Comments[i].commentReplies[i].author.username
You asked specifically for a way using .reduce so here is one solution using .reduce along with lots of destructuring:
const usernames = arr.reduce((names, { author: { username }, Comments }) => {
names.push(username);
Comments.forEach(({ author: { username }, commentReplies }) => {
names.push(username);
commentReplies.forEach(({ author: { username } }) => names.push(username));
});
return names;
}, []);
Live example:
'use strict';
const arr = [
{
"id": 5,
"title": "buttercup",
"postContent": "dsdsfsfsfsfsfs",
"likedByMe": false,
"likeCounts": 0,
"userId": 1,
"createdAt": "2020-08-17T03:41:16.749Z",
"updatedAt": "2020-08-17T03:41:16.749Z",
"author": {
"username": "blankman",
"gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
"bio": null
},
"Likes": [],
"Comments": [{
"id": 46,
"comment_body": "fsfsfsfsfsf",
"gifUrl": "",
"userId": 1,
"postId": 5,
"createdAt": "2020-08-18T04:46:08.946Z",
"updatedAt": "2020-08-18T04:46:08.946Z",
"commentReplies": [{
"id": 18,
"replyBody": "fsfsffsffsffsf",
"userId": 2,
"commentId": 46,
"postId": 5,
"createdAt": "2020-08-21T16:40:47.205Z",
"updatedAt": "2020-08-21T16:40:47.205Z",
"author": {
"username": "barnowl",
"gravatar": null,
"bio": null
}
}],
"author": {
"username": "blankman2",
"gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
"bio": null
}
},
{
"id": 47,
"comment_body": "fsfsfsfsfsf",
"gifUrl": "",
"userId": 1,
"postId": 5,
"createdAt": "2020-08-18T04:46:08.946Z",
"updatedAt": "2020-08-18T04:46:08.946Z",
"commentReplies": [{
"id": 18,
"replyBody": "fsfsffsffsffsf",
"userId": 2,
"commentId": 46,
"postId": 5,
"createdAt": "2020-08-21T16:40:47.205Z",
"updatedAt": "2020-08-21T16:40:47.205Z",
"author": {
"username": "barnowl2",
"gravatar": null,
"bio": null
}
}],
"author": {
"username": "blankman3",
"gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN",
"bio": null
}
},
],
"RePosts": [],
"RepostedByMe": false
}
];
// author.username
// Comments[i].author.username
// Comments[i].commentReplies[i].author.username
const usernames = arr.reduce((names, { author: { username }, Comments }) => {
names.push(username);
Comments.forEach(({ author: { username }, commentReplies }) => {
names.push(username);
commentReplies.forEach(({ author: { username } }) => names.push(username));
});
return names;
}, []);
console.log(usernames);
// => [ 'blankman', 'blankman2', 'barnowl', 'blankman3', 'barnowl2' ]

You would need a recursive function. With flatMap you can ensure that the recursively returned arrays are put together as a single flat array.
Here is a possible implementation that doesn't depend on property names like "Comments" and "commentReplies", but just scans all arrays:
const collect = arr => Array.isArray(arr) ? arr.flatMap(value =>
[value.author?.username].concat(Object.values(value).flatMap(collect))
).filter(Boolean) : [];
// demo
const arr = [{"id": 5,"title": "buttercup","postContent": "dsdsfsfsfsfsfs","likedByMe": false,"likeCounts": 0,"userId": 1,"createdAt": "2020-08-17T03:41:16.749Z","updatedAt": "2020-08-17T03:41:16.749Z","author": {"username": "blankman","gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN","bio": null},"Likes": [],"Comments": [{"id": 46,"comment_body": "fsfsfsfsfsf","gifUrl": "","userId": 1,"postId": 5,"createdAt": "2020-08-18T04:46:08.946Z","updatedAt": "2020-08-18T04:46:08.946Z","commentReplies": [{"id": 18,"replyBody": "fsfsffsffsffsf","userId": 2,"commentId": 46,"postId": 5,"createdAt": "2020-08-21T16:40:47.205Z","updatedAt": "2020-08-21T16:40:47.205Z","author": {"username": "barnowl","gravatar": null,"bio": null}}],"author": {"username": "blankman2","gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN","bio": null}},{"id": 47,"comment_body": "fsfsfsfsfsf","gifUrl": "","userId": 1,"postId": 5,"createdAt": "2020-08-18T04:46:08.946Z","updatedAt": "2020-08-18T04:46:08.946Z","commentReplies": [{"id": 18,"replyBody": "fsfsffsffsffsf","userId": 2,"commentId": 46,"postId": 5,"createdAt": "2020-08-21T16:40:47.205Z","updatedAt": "2020-08-21T16:40:47.205Z","author": {"username": "barnowl2","gravatar": null,"bio": null}}],"author": {"username": "blankman3","gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN","bio": null}},],"RePosts": [],"RepostedByMe": false}];
console.log(collect(arr));
If you find this functional expression syntax confusing, then here is something similar in a more verbose manner:
function collect(arr) {
if (!Array.isArray(arr)) return [];
let result = [];
for (let obj of arr) {
result.push(obj.author?.username);
for (let key in obj) {
result = result.concat(collect(obj[key]));
}
}
return result.filter(Boolean); // exclude null/undefined values
}
// demo
const arr = [{"id": 5,"title": "buttercup","postContent": "dsdsfsfsfsfsfs","likedByMe": false,"likeCounts": 0,"userId": 1,"createdAt": "2020-08-17T03:41:16.749Z","updatedAt": "2020-08-17T03:41:16.749Z","author": {"username": "blankman","gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN","bio": null},"Likes": [],"Comments": [{"id": 46,"comment_body": "fsfsfsfsfsf","gifUrl": "","userId": 1,"postId": 5,"createdAt": "2020-08-18T04:46:08.946Z","updatedAt": "2020-08-18T04:46:08.946Z","commentReplies": [{"id": 18,"replyBody": "fsfsffsffsffsf","userId": 2,"commentId": 46,"postId": 5,"createdAt": "2020-08-21T16:40:47.205Z","updatedAt": "2020-08-21T16:40:47.205Z","author": {"username": "barnowl","gravatar": null,"bio": null}}],"author": {"username": "blankman2","gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN","bio": null}},{"id": 47,"comment_body": "fsfsfsfsfsf","gifUrl": "","userId": 1,"postId": 5,"createdAt": "2020-08-18T04:46:08.946Z","updatedAt": "2020-08-18T04:46:08.946Z","commentReplies": [{"id": 18,"replyBody": "fsfsffsffsffsf","userId": 2,"commentId": 46,"postId": 5,"createdAt": "2020-08-21T16:40:47.205Z","updatedAt": "2020-08-21T16:40:47.205Z","author": {"username": "barnowl2","gravatar": null,"bio": null}}],"author": {"username": "blankman3","gravatar": "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN","bio": null}},],"RePosts": [],"RepostedByMe": false}];
console.log(collect(arr));

You could take a recursion by handing over the key of the parent object.
It works with three steps,
check if the handed over value is an array and if not return an empty array,
check if parent key is author and if property username exist, then take the value of the username property.
get the entries of the object and get all usernames with a recursion by handing over the parent key.
const
getUsernames = (object, parent) => {
if (!object || typeof object !== 'object') return [];
const temp = [];
if (parent === 'author' && 'username' in object) temp.push(object.username);
return [
...temp,
...Object.entries(object).flatMap(([k, v]) => getUsernames(v, k))
];
},
data = [{ id: 5, title: "buttercup", postContent: "dsdsfsfsfsfsfs", likedByMe: false, likeCounts: 0, userId: 1, createdAt: "2020-08-17T03:41:16.749Z", updatedAt: "2020-08-17T03:41:16.749Z", author: { username: "blankman", gravatar: "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN", bio: null }, Likes: [], Comments: [{ id: 46, comment_body: "fsfsfsfsfsf", gifUrl: "", userId: 1, postId: 5, createdAt: "2020-08-18T04:46:08.946Z", updatedAt: "2020-08-18T04:46:08.946Z", commentReplies: [{ id: 18, replyBody: "fsfsffsffsffsf", userId: 2, commentId: 46, postId: 5, createdAt: "2020-08-21T16:40:47.205Z", updatedAt: "2020-08-21T16:40:47.205Z", author: { username: "barnowl", gravatar: null, bio: null } }], author: { username: "blankman2", gravatar: "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN", bio: null } }, { id: 47, comment_body: "fsfsfsfsfsf", gifUrl: "", userId: 1, postId: 5, createdAt: "2020-08-18T04:46:08.946Z", updatedAt: "2020-08-18T04:46:08.946Z", commentReplies: [{ id: 18, replyBody: "fsfsffsffsffsf", userId: 2, commentId: 46, postId: 5, createdAt: "2020-08-21T16:40:47.205Z", updatedAt: "2020-08-21T16:40:47.205Z", author: { username: "barnowl2", gravatar: null, bio: null } }], author: { username: "blankman3", gravatar: "https://lh3.googleusercontent.com/a-/AOh14GiZAw_0UZmt7X0pJFSIv6ELQMd2nN41v0a-eKrN", bio: null } }], RePosts: [], RepostedByMe: false }],
result = getUsernames(data);
console.log(result);

Related

How can I filter a response in reactjs

I need to filter some data from a big complex object which is received as a response to a function.
function showchat() {
dispatch(fetchChats())
.then((res) => {
document.write(JSON.stringify(res));
})
.catch((err) => console.log(err));
}
fetchChats is a function that provides me a object response as:
[
{
"id": 13,
"type": "dual",
"createdAt": "2022-11-01T18:42:08.487Z",
"updatedAt": "2022-11-01T18:42:08.487Z",
"ChatUser": {
"chatId": 13,
"userId": 72,
"createdAt": "2022-11-01T18:42:08.499Z",
"updatedAt": "2022-11-01T18:42:08.499Z"
},
"Users": [
{
"avtar": "http://127.0.0.1:3000/male.svg",
"id": 71,
"firstName": "dhruv",
"lastName": "parmar",
"email": "dhruvdp.js#gmail.com",
"password": "$2b$10$VYQdhqz2ig3NP/8tbJtGHu9kWuNsym4oFobpdy9QLuTJPzQSBq0TG",
"gender": "male",
"createdAt": "2022-11-01",
"updatedAt": "2022-11-01",
"ChatUser": {
"chatId": 13,
"userId": 71,
"createdAt": "2022-11-01T18:42:08.499Z",
"updatedAt": "2022-11-01T18:42:08.499Z"
},
"status": "offline"
}
],
"Messages": [
{
"message": "Bhai kaisa hai?",
"id": 13,
"type": "text",
"chatId": 13,
"fromuserId": 71,
"createdAt": "2022-11-01T18:42:08.505Z",
"updatedAt": "2022-11-01T18:42:08.505Z",
"User": {
"avtar": "http://127.0.0.1:3000/male.svg",
"id": 71,
"firstName": "dhruv",
"lastName": "parmar",
"email": "dhruvdp.js#gmail.com",
"password": "$2b$10$VYQdhqz2ig3NP/8tbJtGHu9kWuNsym4oFobpdy9QLuTJPzQSBq0TG",
"gender": "male",
"createdAt": "2022-11-01",
"updatedAt": "2022-11-01"
}
},
{
"message": "Badiya bhai tu bata",
"id": 14,
"type": "text",
"chatId": 13,
"fromuserId": 72,
"createdAt": "2022-11-01T18:42:08.505Z",
"updatedAt": "2022-11-01T18:42:08.505Z",
"User": {
"avtar": "http://127.0.0.1:3000/male.svg",
"id": 72,
"firstName": "Harshit",
"lastName": "rajpal",
"email": "harshit#gmail.com",
"password": "$2b$10$pGZ./D2axPY4WE.raJW0eOSIX11RluimkIMQ7bDwWgYBsyzhrBFtu",
"gender": "male",
"createdAt": "2022-11-01",
"updatedAt": "2022-11-01"
}
},
{
"message": "Bass apki kripa",
"id": 15,
"type": "text",
"chatId": 13,
"fromuserId": 71,
"createdAt": "2022-11-01T18:42:08.505Z",
"updatedAt": "2022-11-01T18:42:08.505Z",
"User": {
"avtar": "http://127.0.0.1:3000/male.svg",
"id": 71,
"firstName": "dhruv",
"lastName": "parmar",
"email": "dhruvdp.js#gmail.com",
"password": "$2b$10$VYQdhqz2ig3NP/8tbJtGHu9kWuNsym4oFobpdy9QLuTJPzQSBq0TG",
"gender": "male",
"createdAt": "2022-11-01",
"updatedAt": "2022-11-01"
}
}
]
}
]
Now I need to filter all the 'message' from this object but I am comfused
Your question is unclear, you want to filter the message, but filter it based on what?
Do you mean you just want to extract the messages?
This one extracts with ids for reference
const messages = obj.map(x => {return { parentId: x.id, messages: x.Messages.map(x => {return {id: x.id, messages: x.message}})}})
This one extracts just messages for each Chat object
const messages = obj.map(x => x.Messages.map(x => x.message))
And this one flattens it
const messages = obj.map(x => x.Messages.map(x => x.message)).flat()

Javascript: how overwrite/rename the keys of an object?

Let's say I have this object
[{
"id": 2,
"email": "admin#example.com",
"role_id": 1,
"is_active": 1,
"created_at": "2020-10-10T17:05:34.000000Z",
"updated_at": "2020-10-10T17:05:34.000000Z",
"deleted_at": null
}, {
"id": 3,
"email": "agency_owner#example.com",
"role_id": 2,
"is_active": 1,
"created_at": "2020-10-11T18:30:06.000000Z",
"updated_at": "2020-10-11T18:33:51.000000Z",
"deleted_at": null
}]
I would get another object:
[{
"value": 2,
"text": "admin#example.com",
}, {
"value": 3,
"text": "agency_owner#example.com",
}, {
"value": 4,
"text": "license_owner#example.com",
}]
So, renaming "id" with "value" and "email" with "text".
I would use map and maybe not installing lodash or similar...
Thank you...
Well, map is a great idea. What is stopping you from using it?
You can:
obj = [{
"id": 2,
"email": "admin#example.com",
"role_id": 1,
"is_active": 1,
"created_at": "2020-10-10T17:05:34.000000Z",
"updated_at": "2020-10-10T17:05:34.000000Z",
"deleted_at": null
}, {
"id": 3,
"email": "agency_owner#example.com",
"role_id": 2,
"is_active": 1,
"created_at": "2020-10-11T18:30:06.000000Z",
"updated_at": "2020-10-11T18:33:51.000000Z",
"deleted_at": null
}]
obj = obj.map(e => { return {
value: e.id,
text: e.email
}})
console.log(obj)
You can use map as you mentioned:
var arr = [{
"id": 2,
"email": "admin#example.com",
"role_id": 1,
"is_active": 1,
"created_at": "2020-10-10T17:05:34.000000Z",
"updated_at": "2020-10-10T17:05:34.000000Z",
"deleted_at": null
}, {
"id": 3,
"email": "agency_owner#example.com",
"role_id": 2,
"is_active": 1,
"created_at": "2020-10-11T18:30:06.000000Z",
"updated_at": "2020-10-11T18:33:51.000000Z",
"deleted_at": null
}];
var result = arr.map(o => {
return { value: o.id, email: o.email}
});
console.log(result);
[{
"id": 2,
"email": "admin#example.com",
"role_id": 1,
"is_active": 1,
"created_at": "2020-10-10T17:05:34.000000Z",
"updated_at": "2020-10-10T17:05:34.000000Z",
"deleted_at": null
}, {
"id": 3,
"email": "agency_owner#example.com",
"role_id": 2,
"is_active": 1,
"created_at": "2020-10-11T18:30:06.000000Z",
"updated_at": "2020-10-11T18:33:51.000000Z",
"deleted_at": null
}].map(function(obj){
return {
value:obj.id,
text:obj.email
}
})

foreach js reformat data

i am creating a rest API and i get data from one of my request
but i want to parse them
i try to create a foreach loop but a get in every line the same result
there
is a sample of my data
result = [
{
"id": 1,
"UserID": 2,
"idFriend": 3,
"status": "pending",
"UserId": 2,
"User": {
"id": 2,
"email": "toto#gmail.com",
"username": "tetar",
"isAdmin": false,
"isOut": false,
"bio": null,
}
},
{
"id": 2,
"UserID": 2,
"idFriend": 1,
"status": "pending",
"UserId": 2,
"User": {
"id": 2,
"email": "toto#gmail.com",
"username": "tetar",
"isAdmin": false,
"isOut": false,
"bio": null,
}
},
]
and i want to get my data modifed like
`result = [{
"id"= 1,
"User": {
"id": 2,
"email": "toto#gmail.com",
"username": "tetar"
}
},
{
"id"= 2,
"User": {
"id": 2,
"email": "titi#gmail.com",
"username": "tetar"
}
}
}]`
do you know how can i do it ?
thx a lot
Just a mapping function.
const newResult = [];
result.forEach((r) => {
newResult.push({
id: r.id,
user: {
id: r.User.id,
email: r.User.email,
username: r.User.username
}
});
});
console.log(newResult);
I am pretty sure there are better cleaner and more performant ways to do this. I recommend using lodash map function:
https://lodash.com/docs/4.17.5#map
You can use Array.prototype.map:
result = [
{
"id": 1,
"UserID": 2,
"idFriend": 3,
"status": "pending",
"UserId": 2,
"User": {
"id": 2,
"email": "toto#gmail.com",
"username": "tetar",
"isAdmin": false,
"isOut": false,
"bio": null,
}
},
{
"id": 2,
"UserID": 2,
"idFriend": 1,
"status": "pending",
"UserId": 2,
"User": {
"id": 2,
"email": "toto#gmail.com",
"username": "tetar",
"isAdmin": false,
"isOut": false,
"bio": null,
}
},
]
let out = result.map(el=>{return {id: el.id, User:{id: el.User.id, email: el.User.email, username:el.User.username}}});
console.log(out);

Group array by StudentId and find sum of subarrays with same element

[
{
"id": 1,
"subject": "FUNDAMENTALS OF INFORMATION TECHNOLOGY",
"present": "false",
"date": "2018-03-04",
"createdAt": "2018-03-04T14:06:18.000Z",
"updatedAt": "2018-03-04T14:06:18.000Z",
"SemesterId": 1,
"BatchId": 1,
"StudentId": 1,
"Student": {
"id": 1,
"rollnumber": 11111,
"studentname": "LAWANNA HAUGHT",
"dateofbirth": "1997-1-01",
"mobilenumber": "9875449112",
"createdAt": "2018-03-03T14:59:01.000Z",
"updatedAt": "2018-03-03T14:59:01.000Z",
"BatchId": 1
}
},
{
"id": 7,
"subject": "COMPUTER ORGANIZATION",
"present": "true",
"date": "2018-03-04",
"createdAt": "2018-03-04T14:09:12.000Z",
"updatedAt": "2018-03-04T14:09:12.000Z",
"SemesterId": 1,
"BatchId": 1,
"StudentId": 1,
"Student": {
"id": 1,
"rollnumber": 11111,
"studentname": "LAWANNA HAUGHT",
"dateofbirth": "1997-1-01",
"mobilenumber": "9875449112",
"createdAt": "2018-03-03T14:59:01.000Z",
"updatedAt": "2018-03-03T14:59:01.000Z",
"BatchId": 1
}
},
{
"id": 2,
"subject": "FUNDAMENTALS OF INFORMATION TECHNOLOGY",
"present": "true",
"date": "2018-03-04",
"createdAt": "2018-03-04T14:06:18.000Z",
"updatedAt": "2018-03-04T14:06:18.000Z",
"SemesterId": 1,
"BatchId": 1,
"StudentId": 2,
"Student": {
"id": 2,
"rollnumber": 11112,
"studentname": "KAILA HALBROOK",
"dateofbirth": "1997-1-01",
"mobilenumber": "9875449113",
"createdAt": "2018-03-03T14:59:01.000Z",
"updatedAt": "2018-03-03T14:59:01.000Z",
"BatchId": 1
}
},
{
"id": 8,
"subject": "COMPUTER ORGANIZATION",
"present": "false",
"date": "2018-03-04",
"createdAt": "2018-03-04T14:09:12.000Z",
"updatedAt": "2018-03-04T14:09:12.000Z",
"SemesterId": 1,
"BatchId": 1,
"StudentId": 2,
"Student": {
"id": 2,
"rollnumber": 11112,
"studentname": "KAILA HALBROOK",
"dateofbirth": "1997-1-01",
"mobilenumber": "9875449113",
"createdAt": "2018-03-03T14:59:01.000Z",
"updatedAt": "2018-03-03T14:59:01.000Z",
"BatchId": 1
}
}
]
This is an attendance record of one batch.
I'm trying to transform this array to the following form.
All the records with a particular StudentId must be together with one StudentId and studentname.
[
{
"StudentId": 1,
"studentname": "LAWANNA HAUGHT",
"rollnumber": 11111,
"attendance": [
{
"subject": "FUNDAMENTALS OF INFORMATION TECHNOLOGY",
"present": 0,
"absent": 1,
"total": 1
},
{
"subject": "COMPUTER ORGANIZATION",
"present": 1,
"absent": 0,
"total": 1
}
]
},
{
"StudentId": 2,
"studentname": "KAILA HALBROOK",
"rollnumber": 11111,
"attendance": [
{
"subject": "FUNDAMENTALS OF INFORMATION TECHNOLOGY",
"present": 1,
"absent": 0,
"total": 1
},
{
"subject": "COMPUTER ORGANIZATION",
"present": 0,
"absent": 1,
"total": 1
}
]
}
]
present is the number of rows with same StudentId and subjectname and present=true
absent is the number of rows with same StudentId and subjectname and present=false
total is the number of rows with same StudentId and subjectname.
This is the code I have written with the help of one StackOverflow answer and using underscore.js.
But it finds present, absent and total values of all, not by StudentId and subject.
var groups = _.groupBy(list, 'StudentId');
var result = _.map(groups, function(student){
return {
StudentId: student[0].StudentId,
studentname: student[0].Student.studentname,
rollnumber: student[0].Student.rollnumber,
attendances: _.map(student, function(item){
return {
subject:item.subject,
present: _.reduce(item, function(memo, att){
if(att.present=='true')
return memo + 1;
else
return memo;
}, 0),
absent: _.reduce(item, function(memo, att){
if(att.present=='false')
return memo + 1;
else
return memo;
}, 0),
total: _.reduce(item, function(memo, att){
return memo + 1;
}, 0)
}
})
})
}
}
);
You could use a nested approach by looking for strunden and later for looking for attendance.
var data = [{ id: 1, subject: "FUNDAMENTALS OF INFORMATION TECHNOLOGY", present: "false", date: "2018-03-04", createdAt: "2018-03-04T14:06:18.000Z", updatedAt: "2018-03-04T14:06:18.000Z", SemesterId: 1, BatchId: 1, StudentId: 1, Student: { id: 1, rollnumber: 11111, studentname: "LAWANNA HAUGHT", dateofbirth: "1997-1-01", mobilenumber: "9875449112", createdAt: "2018-03-03T14:59:01.000Z", updatedAt: "2018-03-03T14:59:01.000Z", BatchId: 1 } }, { id: 7, subject: "COMPUTER ORGANIZATION", present: "true", date: "2018-03-04", createdAt: "2018-03-04T14:09:12.000Z", updatedAt: "2018-03-04T14:09:12.000Z", SemesterId: 1, BatchId: 1, StudentId: 1, Student: { id: 1, rollnumber: 11111, studentname: "LAWANNA HAUGHT", dateofbirth: "1997-1-01", mobilenumber: "9875449112", createdAt: "2018-03-03T14:59:01.000Z", updatedAt: "2018-03-03T14:59:01.000Z", BatchId: 1 } }, { id: 2, subject: "FUNDAMENTALS OF INFORMATION TECHNOLOGY", present: "true", date: "2018-03-04", createdAt: "2018-03-04T14:06:18.000Z", updatedAt: "2018-03-04T14:06:18.000Z", SemesterId: 1, BatchId: 1, StudentId: 2, Student: { id: 2, rollnumber: 11112, studentname: "KAILA HALBROOK", dateofbirth: "1997-1-01", mobilenumber: "9875449113", createdAt: "2018-03-03T14:59:01.000Z", updatedAt: "2018-03-03T14:59:01.000Z", BatchId: 1 } }, { id: 8, subject: "COMPUTER ORGANIZATION", present: "false", date: "2018-03-04", createdAt: "2018-03-04T14:09:12.000Z", updatedAt: "2018-03-04T14:09:12.000Z", SemesterId: 1, BatchId: 1, StudentId: 2, Student: { id: 2, rollnumber: 11112, studentname: "KAILA HALBROOK", dateofbirth: "1997-1-01", mobilenumber: "9875449113", createdAt: "2018-03-03T14:59:01.000Z", updatedAt: "2018-03-03T14:59:01.000Z", BatchId: 1 } }],
grouped = [];
data.forEach(({ subject, present, StudentId, Student: { rollnumber, studentname } }) => {
var student = grouped.find(g => StudentId === g.StudentId),
attendance;
if (!student) {
student = { StudentId, studentname, rollnumber, attendance: [] };
grouped.push(student);
}
attendance = student.attendance.find(a => a.subject === subject);
if (!attendance) {
attendance = { subject, present: 0, absent: 0, total: 0 };
student.attendance.push(attendance);
}
attendance[{ true: 'present', false: 'absent' }[present]]++;
attendance.total++;
});
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Okay, this came out a little weird. If you are coding the backend, it may make sense to handle this on the query end. That being said, you can use reduce to "collapse" the array into an object based on the StudentId. In this process, you can build out the shape of what the record should look like. I don't this is a standard way of using reduce since you are transforming an array. That being said, I couldn't think of an easy way of using map. The result of this operation gives us an object, we can get it back to an array using Object.values(). I don't understand the use case for present, absent, and total.
Here is the JSFiddle.
function isolateRecords(data) {
return Object.values(data.reduce((accum, current) => {
let attenance = {
subject: current.subject,
present: current.present === "true" ? 1 : 0,
absent: current.present === "false" ? 1 : 0,
total: 0
};
attenance.total = attenance.present + attenance.absent;
if (accum[current.StudentId]) {
accum[current.StudentId].attendance.push(attenance);
} else {
accum[current.StudentId] = {
StudentId: current.StudentId,
studentname: current.Student.studentname,
rollnumber: current.Student.rollnumber,
attendance: [attenance]
}
}
return accum;
}, {}));
}
isolateRecords(myOriginalArrayOfRecords);

JSON Object Transformation into specific Javascript Array or JSON Object

So I have this JSON Object. Let's call it var dataFetched
var dataFetched = {
"status": "ok",
"count": 4,
"count_total": 4,
"pages": 1,
"posts": [
{
"id": 57,
"type": "keyword",
"slug": "crime-scene-investigation-csi",
"url": "http://keyjargon.com/keyword/crime-scene-investigation-csi/",
"status": "publish",
"title": "Crime Scene Investigation (CSI)",
"title_plain": "Crime Scene Investigation (CSI)",
"content": "",
"excerpt": "",
"date": "2015-11-07 05:01:51",
"modified": "2015-11-07 05:01:51",
"categories": [
{
"id": 8,
"slug": "law",
"title": "Law",
"description": "",
"parent": 0,
"post_count": 1
}
],
"tags": [
],
"author": {
"id": 1,
"slug": "admin",
"name": "admin",
"first_name": "",
"last_name": "",
"nickname": "admin",
"url": "",
"description": ""
},
"comments": [
],
"attachments": [
],
"comment_count": 0,
"comment_status": "closed",
"custom_fields": {
}
},
{
"id": 50,
"type": "keyword",
"slug": "fx",
"url": "http://keyjargon.com/keyword/fx/",
"status": "publish",
"title": "FX",
"title_plain": "FX",
"content": "",
"excerpt": "",
"date": "2015-11-05 10:07:17",
"modified": "2015-11-05 10:22:10",
"categories": [
{
"id": 3,
"slug": "business",
"title": "Business",
"description": "",
"parent": 0,
"post_count": 2
}
],
"tags": [
],
"author": {
"id": 1,
"slug": "admin",
"name": "admin",
"first_name": "",
"last_name": "",
"nickname": "admin",
"url": "",
"description": ""
},
"comments": [
],
"attachments": [
],
"comment_count": 0,
"comment_status": "closed",
"custom_fields": {
}
},
{
"id": 48,
"type": "keyword",
"slug": "common-core",
"url": "http://keyjargon.com/keyword/common-core/",
"status": "publish",
"title": "Common CORE",
"title_plain": "Common CORE",
"content": "",
"excerpt": "",
"date": "2015-11-05 10:06:40",
"modified": "2015-11-07 04:58:06",
"categories": [
{
"id": 2,
"slug": "technology",
"title": "Technology",
"description": "",
"parent": 0,
"post_count": 3
}
],
"tags": [
],
"author": {
"id": 1,
"slug": "admin",
"name": "admin",
"first_name": "",
"last_name": "",
"nickname": "admin",
"url": "",
"description": ""
},
"comments": [
],
"attachments": [
],
"comment_count": 0,
"comment_status": "closed",
"custom_fields": {
}
},
{
"id": 46,
"type": "keyword",
"slug": "api",
"url": "http://keyjargon.com/keyword/api/",
"status": "publish",
"title": "API",
"title_plain": "API",
"content": "",
"excerpt": "",
"date": "2015-11-05 10:06:19",
"modified": "2015-11-05 10:21:47",
"categories": [
{
"id": 2,
"slug": "technology",
"title": "Technology",
"description": "",
"parent": 0,
"post_count": 3
}
],
"tags": [
],
"author": {
"id": 1,
"slug": "admin",
"name": "admin",
"first_name": "",
"last_name": "",
"nickname": "admin",
"url": "",
"description": ""
},
"comments": [
],
"attachments": [
],
"comment_count": 0,
"comment_status": "closed",
"custom_fields": {
}
}
]
}
I want to rearrange this result to link the Category title :
dataFetched.posts[i].categories[0].title
to the Post title :
dataFetched.post[i].title
so that each category displays all the posts titles related to it. I want my object (whether multi-demmensional array or another object) to be able to retrieve all the Posts titles related to the category.
Maybe something like this :
[Category1: {Post_titleA, PostTitleB, PostTitleC}, Category2: {PostTileF, PostTileX}, etc ] where each category can retrieve all its posts.( The format does not matter as long the Object with Category title X can retrieve all posts titles that belong to it ).
How do I do this in Javascript ? The result variable is not static but its format is the same as the one posted here.
This is what I tried so far.
// Function to sort unique values of an array
function sort_unique(arr) {
arr = arr.sort(function (a, b) { return a*1 - b*1; });
var ret = [arr[0]];
for (var i = 1; i < arr.length; i++) { // start loop at 1 as element 0 can never be a duplicate
if (arr[i-1] !== arr[i]) {
ret.push(arr[i]);
}
}
return ret;
}
//Define two arrays to be used for categories and Keywords
var keywords = [];
var industries = [];
//Fill up the categories(Industries) array and the keywords one
for ( var i = 0, iLen = dataFetched.count; i < iLen; i++) {
keywords[i] = dataFetched.posts[i].title;
industries[i] = dataFetched.posts[i].categories[0].title;
}
// Sort and eliminate duplication of category and keyword names
keywords = sort_unique(keywords);
industries = sort_unique(industries);
// Now time for trouble: Define a multi-dimmensional array that links each category/industry to its keywords **This is where I AM STUCK**
ind = new Array;
for(i=0; i<industries.length;i++){
ind[i] = new Array;
}
for(i=0;i<dataFetched.count;i++){
ind[i][0]= dataFetched.posts[i].categories[0].title;
for(j=0;j<dataFetched.count;j++){
var count = ind[i].length;
if(ind[i][0] == dataFetched.posts[j].categories[0].title){
ind[i][count] = dataFetched.posts[j].title;
}
}
}
It is possible to create object with categories. As a result all entries can be accessed by category name and you do not need to sort them to have unique titles:
var posts = dataFetched.posts;
var cat = {};
posts.forEach(
function(p) {
p.categories.forEach(
function(c) {
if (!cat[c.title])
cat[c.title] = [];
cat[c.title].push(p.title);
});
});
console.log(cat);
Output for your example:
Object {Law: Array[1], Business: Array[1], Technology: Array[2]}
Each category title is a key in this object and the arrays of posts are values of those keys.
The output example you showed is wrong, in JS there's no object like
[Category1: {Post_titleA, PostTitleB, PostTitleC}, Category2: {PostTileF, PostTileX}, etc ]
The most similar thing you can get is a JSON object like this:
{
"Category1" : ["Post_titleA", "PostTitleB", "PostTitleC"],
"Category2" : ["PostTileF", "PostTileX"],
//etc..
}
In order to achieve this, you can use the following function:
function getTitlesByCategory (json) {
var result = {}
json.posts.map(function (post) {
post.categories.map(function (category) {
result[category.title] = result[category.title] || [];
result[category.title].push(post.title);
});
});
return result;
}

Categories