Reputation: 3589
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)
Upvotes: 1
Views: 786
Reputation: 386604
You could take a recursion by handing over the key of the parent object.
It works with three steps,
author
and if property username
exist, then take the value of the username
property.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);
Upvotes: 1
Reputation: 350272
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));
Upvotes: 1
Reputation: 4912
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' ]
Upvotes: 1
Reputation: 1058
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));
Upvotes: 3
Reputation: 10729
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)
Upvotes: 1
Reputation: 89264
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);
Upvotes: 2