Related
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
}
})
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);
This is an example of an api response
[
{
"id": 1,
"name": "Medicine1",
"status": true,
"location": "E1-2",
"genericName": "Medicine1 Generic name",
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 1,
"name": "Tabletas"
},
"measure": {
"id": 1,
"unit": "Gramos",
"abbreviation": "g"
},
"quantity": 25,
"percentage": null
},
{
"id": 2,
"name": "Medicine2",
"status": true,
"location": "E1-5",
"genericName": "Medicine2 Generic",
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 2,
"name": "Cremas"
},
"measure": {
"id": 1,
"unit": "Gramos",
"abbreviation": "g"
},
"quantity": 500,
"percentage": null
},
{
"id": 3,
"name": "Medicine3",
"status": true,
"location": "E1-2",
"genericName": null,
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 3,
"name": "Unguentos"
},
"measure": {
"id": 3,
"unit": "Libras",
"abbreviation": "lb"
},
"quantity": 5,
"percentage": null
},
{
"id": 4,
"name": "Medicine4",
"status": true,
"location": "E5-1",
"genericName": null,
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 1,
"name": "Tabletas"
},
"measure": {
"id": 2,
"unit": "Kilogramos",
"abbreviation": "kg"
},
"quantity": 5,
"percentage": null
},
{
"id": 5,
"name": "Medicine5",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 1,
"name": "Tabletas"
},
"measure": {
"id": 1,
"unit": "Gramos",
"abbreviation": "g"
},
"quantity": 5,
"percentage": null
},
{
"id": 6,
"name": "Medicine5",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 1,
"name": "Tabletas"
},
"measure": {
"id": 1,
"unit": "Gramos",
"abbreviation": "g"
},
"quantity": 5,
"percentage": null
},
{
"id": 7,
"name": "Medicine6",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": {
"id": null,
"name": null
},
"presentation": {
"id": 1,
"name": "Tabletas"
},
"measure": {
"id": 1,
"unit": "Gramos",
"abbreviation": "g"
},
"quantity": 5,
"percentage": null
},
{
"id": 8,
"name": "Medicine7",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": {
"id": 3,
"name": "Falcon"
},
"presentation": {
"id": 4,
"name": "Gotas"
},
"measure": {
"id": 1,
"unit": "Gramos",
"abbreviation": "g"
},
"quantity": 5,
"percentage": null
}
]
As you can see, the laboratory, percentage and genericName keys can have null value.
I need to filter this response according to a criteria that should be compared with each value
Here is the filter code
const criteria = 'some text';
fetchResource('medicines').then(medicines => {
const results = medicines.filter(medicine => {
return (
medicine.name.toLowerCase().includes(criteria) ||
medicine.genericName.toLowerCase().includes(criteria) ||
medicine.presentation.name
.toLowerCase()
.includes(criteria) ||
medicine.measure.unit.toLowerCase().includes(criteria) ||
medicine.measure.abbreviation
.toLowerCase()
.includes(criteria) ||
medicine.location.toLowerCase().includes(criteria)
);
});
const helper = makeHelper();
helper.render(results);
});
In backend, I thought about excluding the mentioned keys from the response when they do not have values. I have not tried yet but I understand that would work
I appreciate your advice on how to deal with this case on the client's side
There are other answers here that suggest using JSON.stringify to convert the entire object to a string, but that's not a great solution. It would make it impossible to search for generic, because every object has a property named genericName. There is another way to use stringify that's a bit more graceful, and that's to take advantage of the replacer callback.
For example:
const results = medicines.filter(m => {
var isMatch = false;
JSON.stringify(m, (key, value) => {
if (typeof value === "string" && value.toLowerCase().includes(criteria)) {
isMatch = true;
}
return value;
});
return isMatch;
});
results will contain only those entries from medicines that contain some value that is a string that matches the given filter. You can extend this logic to include numeric values, such as id, or exclude certain keys you're not interested in, such as abbreviation.
Here's a quick demo implementing some more advanced logic. You'll of course want to tweak it to suit your exact needs:
const medicines = [{
"id": 1,
"name": "Medicine1",
"status": true,
"location": "E1-2",
"genericName": "Medicine1 Generic name",
"laboratory": { "id": null, "name": null },
"presentation": { "id": 1, "name": "Tabletas" },
"measure": { "id": 1, "unit": "Gramos", "abbreviation": "g" },
"quantity": 25,
"percentage": null
},
{
"id": 2,
"name": "Medicine2",
"status": true,
"location": "E1-5",
"genericName": "Medicine2 Generic",
"laboratory": { "id": null, "name": null },
"presentation": { "id": 2, "name": "Cremas" },
"measure": { "id": 1, "unit": "Gramos", "abbreviation": "g" },
"quantity": 500,
"percentage": null
},
{
"id": 3,
"name": "Medicine3",
"status": true,
"location": "E1-2",
"genericName": null,
"laboratory": { "id": null, "name": null },
"presentation": { "id": 3, "name": "Unguentos" },
"measure": { "id": 3, "unit": "Libras", "abbreviation": "lb" },
"quantity": 5,
"percentage": null
},
{
"id": 4,
"name": "Medicine4",
"status": true,
"location": "E5-1",
"genericName": null,
"laboratory": { "id": null, "name": null },
"presentation": { "id": 1, "name": "Tabletas" },
"measure": { "id": 2, "unit": "Kilogramos", "abbreviation": "kg" },
"quantity": 5,
"percentage": null
},
{
"id": 5,
"name": "Medicine5",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": { "id": null, "name": null },
"presentation": { "id": 1, "name": "Tabletas" },
"measure": { "id": 1, "unit": "Gramos", "abbreviation": "g" },
"quantity": 5,
"percentage": null
},
{
"id": 6,
"name": "Medicine5",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": { "id": null, "name": null },
"presentation": { "id": 1, "name": "Tabletas" },
"measure": { "id": 1, "unit": "Gramos", "abbreviation": "g" },
"quantity": 5,
"percentage": null
},
{
"id": 7,
"name": "Medicine6",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": { "id": null, "name": null },
"presentation": { "id": 1, "name": "Tabletas" },
"measure": { "id": 1, "unit": "Gramos", "abbreviation": "g" },
"quantity": 5,
"percentage": null
},
{
"id": 8,
"name": "Medicine7",
"status": true,
"location": "E1-1",
"genericName": null,
"laboratory": { "id": 3, "name": "Falcon" },
"presentation": { "id": 4, "name": "Gotas" },
"measure": { "id": 1, "unit": "Gramos", "abbreviation": "g" },
"quantity": 5,
"percentage": null
}
];
const btn = document.getElementById("go");
const inp = document.getElementById("search");
btn.addEventListener('click', () => {
const criteria = inp.value.toLowerCase();
const results = medicines.filter(m => {
var isMatch = false;
JSON.stringify(m, (key, value) => {
// Search 'id' values
if (key === "id" && value !== null && value.toString().includes(criteria)) {
isMatch = true;
// Ignore 'abbreviation'
} else if (key !== "abbreviation") {
// Search all other string values
if (typeof value === "string" && value.toLowerCase().includes(criteria)) {
isMatch = true;
}
}
return value;
});
return isMatch;
});
console.log(results);
});
<input id="search" type="search" placeholder="filter" /><button id="go">Go</button><br>
<code>
Currently your code will error on medicine.genericName.toLowerCase() if the genericName field isn't a string. To avoid that you could try one of the following instead:
Fall back to a default:
(medicine.genericName || '').toLowerCase().includes(criteria)
Check the value first:
(medicine.genericName && medicine.genericName.toLowerCase().includes(criteria))
Its a bit tough to figure out what you're trying to do with the example, but I'm assuming you want to check if the value of multiple keys in your API response contains a substring criteria?
If that's the case, you could try something like:
fetchResource('medicines').then(medicines => {
const results = medicines.filter(medicine => {
for (var key in medicine){
if((typeof(medicine[key] == 'string' || typeof(medicine[key] == 'int') && medicine[key].toString().toLowerCase().includes(criteria)){
return true
}
else if(typeof(medicine[key]) === 'object'){
for(var subkey in medicine[key]){
if((typeof(medicine[key][subkey]) == 'string' || typeof(medicine[key][subkey]) === 'int') && medicine[key][subkey].toString().toLowerCase().includes(criteria)){
return true
}
}
}
}
return false
})
})
This is obviously much cleaner than hard coding all of the property names.
As I told before, use a forEach in your array; following a function to filter;
Use JSON.stringify so you que see all properties in row;
Apply a pattern as criteria
var yourCriteria = ""; // or any Regex
var yourArray = [];
var newArray = [];
yourArray.forEach(function(e){
if (JSON.stringify(e).toLowerCase().indexOf(yourCriteria) < 0)
newArray.push(e);
})
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;
}
This question already has answers here:
Sort array of objects by string property value
(57 answers)
Closed 8 years ago.
I have this array and I was wondering if I could sort it with the properties comments.count and likes.count separately.
For example I could just have a function to call using likes.count parameter or comments.count parameter.
{
"attribution": null,
"tags": [
],
"type": "",
"location": null,
"comments": {
"count": 2,
"data": [
{
"created_time": "1385670850",
"text": "Holy shit",
"from": {
"username": "someone",
"profile_picture": "http://url.com/profiles/profile_191120775_75sq_1365830292.jpg",
"id": "191120775"
},
"id": "599372997379438683"
},
{
"created_time": "1385680581",
"text": "",
"from": {
"username": "someone",
"profile_picture": "http://url.com/profiles/profile_1523167_75sq_1389544912.jpg",
"id": "1523167"
},
"id": "599454624038205610"
}
]
},
"likes": {
"count": 6,
"data": [
{
"username": "someone",
"profile_picture": "http://url.com/profiles/profile_2169761_75sq_1389075971.jpg",
"id": "2169761"
},
{
"username": "rashmityagi",
"profile_picture": "http://url.com/profiles/profile_393770264_75sq_1388911033.jpg",
"id": "393770264"
},
{
"username": "tylerferweda",
"profile_picture": "http://url.com/profiles/profile_191120775_75sq_1365830292.jpg",
"id": "191120775"
},
{
"username": "cbolts",
"profile_picture": "http://url.com/profiles/profile_1523167_75sq_1389544912.jpg",
"id": "1523167"
}
]
}
},
{
"attribution": null,
"tags": [
],
"type": "",
"location": null,
"comments": {
"count": 10,
"data": [
{
"created_time": "1385670850",
"text": "Holy shit",
"from": {
"username": "someone",
"profile_picture": "http://url.com/profiles/profile_191120775_75sq_1365830292.jpg",
"id": "191120775"
},
"id": "599372997379438683"
},
{
"created_time": "1385680581",
"text": "",
"from": {
"username": "someone",
"profile_picture": "http://url.com/profiles/profile_1523167_75sq_1389544912.jpg",
"id": "1523167"
},
"id": "599454624038205610"
}
]
},
"likes": {
"count": 20,
"data": [
{
"username": "someone",
"profile_picture": "http://url.com/profiles/profile_2169761_75sq_1389075971.jpg",
"id": "2169761"
},
{
"username": "rashmityagi",
"profile_picture": "http://url.com/profiles/profile_393770264_75sq_1388911033.jpg",
"id": "393770264"
},
{
"username": "tylerferweda",
"profile_picture": "http://url.com/profiles/profile_191120775_75sq_1365830292.jpg",
"id": "191120775"
},
{
"username": "cbolts",
"profile_picture": "http://url.com/profiles/profile_1523167_75sq_1389544912.jpg",
"id": "1523167"
}
]
}
},
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
json_array.sort(function(a, b) {
if(a.comments.count < b.comments.count) {
return -1;
}
if(a.comments.count > b.comments.count) {
return 1;
}
return 0;
});
You can also modify it for likes.count
Underscore.js provides great utility functions for working with arrays and objects. For your case you could use _.sortBy(...) See http://underscorejs.org/#sortBy for more details. For simple object properties it is enough to specify the object property name als last parameter.