Make subcategory as array in object of array - javascript

I'm working on django rest and angular. This json array is coming from server and contains category and subcategory values.
my code will create category and related subcategory in separate keys of array. But i want keep subcategory as a array in object in same object.
Result should be like this:
[{"title":"title of category","sub":[array of related sub]} , ...]
mycode:
public data = SERVERRESPONE;
public categories = [];
this.data.filter(c => c.parent_id === null).map(c => <{ title: {}; subcategories: {} }>{
title: {"title":c.title},
subcategories: this.data.filter(sc => sc.parent_id === c.cat_id).map(sc => sc.title)
}).forEach(c => {
this.categories.push([c.title, [c.subcategories]]);
});
server response :
[
{
"id": 5,
"cat_id": 0,
"parent_id": null,
"title": "web development"
},
{
"id": 6,
"cat_id": 1,
"parent_id": null,
"title": "android development"
},
{
"id": 7,
"cat_id": null,
"parent_id": 0,
"title": "php"
},
{
"id": 8,
"cat_id": null,
"parent_id": 1,
"title": "java"
}
]

it is nice question but it has very easy solution!
const array = [
{
"id": 5,
"cat_id": 0,
"parent_id": null,
"title": "web development"
},
{
"id": 6,
"cat_id": 1,
"parent_id": null,
"title": "android development"
},
{
"id": 7,
"cat_id": null,
"parent_id": 0,
"title": "php"
},
{
"id": 8,
"cat_id": null,
"parent_id": 1,
"title": "java"
}
]
let result = []
for (let key of array) {
if (key.parent_id === null) {
let new_key = key,
sub = []
for (let iterator of array)
if (iterator.parent_id === key.cat_id)
sub.push(iterator)
new_key.sub = sub
result.push(new_key)
}
}
console.log(result)

Related

Filtering JSON multidimensional array using jQuery Grep

I'm trying to filter the 2nd level of array and if it is true will get the 1st level array in JSON data. I'm using jQuery grep to find the specific element of an array and to filter the department and the jobs.title.
In my case I'm trying to search job title "FULL" and the data is under the department of Marketing. So I'm trying to achieve that if the data "FULL" exist under Marketing Department then Display Marketing Department Jobs.
For JSON file I'm using greenhouse API for testing.
{
"departments": [
{
"id": 4009377006,
"name": "Client Success",
"parent_id": null,
"child_ids": [],
"jobs": []
},
{
"id": 4009378006,
"name": "Creative",
"parent_id": null,
"child_ids": [],
"jobs": []
},
{
"id": 4009379006,
"name": "Engineering",
"parent_id": null,
"child_ids": [],
"jobs": [
{
"absolute_url": "https://boards.greenhouse.io/frequence/jobs/4044313006",
"data_compliance": [
{
"type": "gdpr",
"requires_consent": false,
"retention_period": null
}
],
"internal_job_id": 4034527006,
"location": {
"name": "Menlo Park, CA"
},
"metadata": [
{
"id": 4410278006,
"name": "Desired Timezones",
"value": [],
"value_type": "multi_select"
}
],
"id": 4044313006,
"updated_at": "2023-02-02T13:40:43-05:00",
"requisition_id": "TEST101",
"title": "TEST HIRING - SOFTWARE ENGINEER"
}
]
},
{
"id": 4009380006,
"name": "Finance",
"parent_id": null,
"child_ids": [],
"jobs": []
},
{
"id": 4009381006,
"name": "Marketing",
"parent_id": null,
"child_ids": [],
"jobs": [
{
"absolute_url": "https://boards.greenhouse.io/frequence/jobs/4044533006",
"data_compliance": [
{
"type": "gdpr",
"requires_consent": false,
"retention_period": null
}
],
"internal_job_id": 4034679006,
"location": {
"name": "Menlo Park, CA, or New York City, NY, or Washington DC"
},
"metadata": [
{
"id": 4410278006,
"name": "Desired Timezones",
"value": [],
"value_type": "multi_select"
}
],
"id": 4044533006,
"updated_at": "2023-02-02T13:40:43-05:00",
"requisition_id": "TEST103",
"title": "TEST HIRING - FULL STACK DEVELOPER"
},
{
"absolute_url": "https://boards.greenhouse.io/frequence/jobs/4044315006",
"data_compliance": [
{
"type": "gdpr",
"requires_consent": false,
"retention_period": null
}
],
"internal_job_id": 4034529006,
"location": {
"name": "Menlo Park, CA, or New York City, NY, or Washington DC"
},
"metadata": [
{
"id": 4410278006,
"name": "Desired Timezones",
"value": [],
"value_type": "multi_select"
}
],
"id": 4044315006,
"updated_at": "2023-02-02T13:40:43-05:00",
"requisition_id": "TEST102",
"title": "TEST HIRING - PHP DEVELOPER"
}
]
},
{
"id": 4009382006,
"name": "Operations",
"parent_id": null,
"child_ids": [],
"jobs": []
},
{
"id": 4009383006,
"name": "People",
"parent_id": null,
"child_ids": [],
"jobs": []
},
{
"id": 4009384006,
"name": "Product",
"parent_id": null,
"child_ids": [],
"jobs": []
},
{
"id": 4009385006,
"name": "Sales",
"parent_id": null,
"child_ids": [],
"jobs": []
},
{
"id": 0,
"name": "No Department",
"parent_id": null,
"child_ids": [],
"jobs": []
}
]
}
This is what I've been working below.
$.getJSON('https://boards-api.greenhouse.io/v1/boards/frequence/departments/',
function(data) {
var search_term = 'FULL';
var search = search_term.toUpperCase();
var getDepartment = '';
var filterDept = $.grep(data.departments, function (element, index) {
var search_filter = element.name.toUpperCase().indexOf(search) >= 0;
console.log(element);
if(search_filter <= 0){
// I'm trying to achieve here is to check if the element exist in 2nd level of array
//and if true it will retrieve the parent array or 1st level of array.
filterDept = $.grep(element.jobs, function (element1, index1) {
search_filter = element1.title.toUpperCase().indexOf(search) >= 0;
if(search_filter == true) {
search_filter = element.name.toUpperCase().indexOf(search) >= 0;
console.log(element1.title);
return false;
}
});
}
return search_filter;
});
console.log(filterDept);
});
Here is the way I would approach this:
const search_term = 'FULL';
const search = search_term.toUpperCase();
// Use helpful names like "department" and "job" instead of
// "element" and "element1" - this improves readability.
const matches = $.grep(data.departments, function (department) {
const isMatch = department.name.toUpperCase().indexOf(search) >= 0;
// Return `true` early if we have a direct name match.
if (isMatch) { return true; }
// If we haven't matched directly on name, we will filter
// the department's jobs for matches.
const jobMatches = $.grep(department.jobs, function (job) {
return job.title.toUpperCase().indexOf(search) >= 0;
});
// We consider this department to be a match if its filtered
// jobs has any elements (ie., its `.length` is greater than 0).
return jobMatches.length > 0;
});
I have created a fiddle for reference.
Update
I feel I should add that I used jQuery's grep function in my example only because it was mentioned in the question.
I would not use jQuery for this functionality because modern JavaScript has the methods on the Array prototype to do the filtering we require.
Here is an example in plain JavaScript:
const search_term = 'FULL';
const search = search_term.toUpperCase();
const matches = data.departments.filter(department => {
const isMatch = department.name.toUpperCase().indexOf(search) >= 0;
return isMatch || department.jobs.some(job => job.title.toUpperCase().indexOf(search) >= 0);
});
And here is a fiddle that uses this code.

Mongoose Sorting , .sort() queries output is not as expected

My code for sorting episodes in ascending order using episodeNo is
const episodes = await Episode.find({anime: animeId}).sort({episodeNo: 1});
I think it should sort like 1, 2, 3, 4 but it's sorting like 1, 10, 11, 2, 3.
the JSON response is
"id": "607dc50dc21368000414b378",
"episodeNo": 1,
"subtitle": false
},
{
"id": "607dc50dc21368000414b381",
"episodeNo": 10,
"subtitle": false
},
{
"id": "607dc50dc21368000414b382",
"episodeNo": 11,
"subtitle": false
},
{
"id": "607dc50dc21368000414b383",
"episodeNo": 12,
"subtitle": false
},
{
"id": "607dc50dc21368000414b379",
"episodeNo": 2,
"subtitle": false
}

How to set value to json object by condition?

I have a list object returned from server,
example:
{
"items": [
{
"id": 1,
"role": "SYSTEM_ADMIN"
},
{
"id": 2,
"role": "SYSTEM"
},
{
"id": 3,
"role": "USER"
}
]
}
The problem here is that I want to set the rank value of each object in the above json follow the condition:
SYSTEM_ADMIN => rank: 3
SYSTEM => rank: 2
USER => rank 1
example:
{
    "items": [
        {
            "id": 1,
            "role": "SYSTEM_ADMIN",
            "rank": 3
        },
        {
            "id": 2,
            "role": "SYSTEM",
            "rank": 2
        },
        {
            "id": 3,
            "role": "USER",
            "rank": 1
        },
        {
            "id": 4,
            "role": "SYSTEM",
            "rank": 2
        }
    ]
}
How do I use javascript quickly set rank values ​​for the object without if else too much? thanks everyone
As some people suggested, it's best to do it on the server when you create the response.
If you still need to do it on the frontend for some reason, you can create a constant map that stores each role value's rank in an object map:
const rankMap = {
SYSTEM_ADMIN: 3,
SYSTEM: 2,
USER: 1
};
const data = {
"items": [{
"id": 1,
"role": "SYSTEM_ADMIN"
},
{
"id": 2,
"role": "SYSTEM"
},
{
"id": 3,
"role": "USER"
}
]
}
data.items = data.items.map(item => ({
...item,
rank: rankMap[item.role],
}));
console.log(data);
You can create an object which contains rank and then just use map:
let ranks = {SYSTEM_ADMIN: 3, SYSTEM: 2, USER: 1};
let result = items.map(({id, role})=> ({id, role, rank: ranks[role]}));
An example:
let items = [
{
"id": 1,
"role": "SYSTEM_ADMIN"
},
{
"id": 2,
"role": "SYSTEM"
},
{
"id": 3,
"role": "USER"
}
];
let ranks = {SYSTEM_ADMIN: 3, SYSTEM: 2, USER: 1};
let result = items.map(({id, role})=> ({id, role, rank: ranks[role]}));
console.log(result)
I would keep a list of the roles and their respective ranks in a dictionary. The response can then very simply be mapped
let response = {
items: [
{
"id": 1,
"role": "SYSTEM_ADMIN",
},
{
"id": 2,
"role": "SYSTEM",
},
{
"id": 3,
"role": "USER",
},
{
"id": 4,
"role": "SYSTEM",
}
]
}
let rankMap = {
"SYSTEM_ADMIN": 3,
"SYSTEM": 2,
"USER": 1
}
response.items.forEach(i => i['rank'] = rankMap[i.role]);
console.log(response);

Filtering array of objects by an out of order array of IDs in Javascript

Here's an array of book objects.
const books=[
{
"id": 1,
"title": "NPR",
"url": "https://www.npr.org"
},
{
"id": 2,
"title": "Google Docs",
"url": "https://docs.google.com/"
},
{
"title": "Fetch API Docs",
"url": "https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch",
"id": 3
},
{
"title": "Yahoo",
"url": "http://www.yahoo.com",
"id": 4
},
{
"title": "Google",
"url": "http://www.google.com",
"id": 5
}
]
And a separate array of IDs
const selectedIds = [1, 5, 3]
With javascript, how can I filter the books array to just the selectedIds (keeping the same order as in selectedIds)?
Final result I'm looking to get:
selectedBooks = [
{
"id": 1,
"title": "NPR",
"url": "https://www.npr.org"
},
{
"title": "Google",
"url": "http://www.google.com",
"id": 5
},
{
"title": "Fetch API Docs",
"url": "https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch",
"id": 3
}
]
My current code is like this but this preserves the order of the books array (i.e. [1, 3, 5]):
books.filter(function(item) {
return selectedIds.includes(item.id);
}
Go in the other direction.
selectedIds.map(id => books.find(b => b.id === id))
const books = [{
id: 1,
title: "NPR",
url: "https://www.npr.org"
},
{
id: 2,
title: "Google Docs",
url: "https://docs.google.com/"
},
{
title: "Fetch API Docs",
url: "https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch",
id: 3
},
{
title: "Yahoo",
url: "http://www.yahoo.com",
id: 4
},
{
title: "Google",
url: "http://www.google.com",
id: 5
}
];
const selectedIds = [1, 5, 3];
const mapped = selectedIds.map(id => {
return books.find(book => book.id === id);
});
console.log(mapped);

Javascript - grab value inside of an object nested within an object

I am trying to grab a value of a key inside of an object in an array which itself is an object in an array.
Here is what it looks like:
var books = [
{
"title": "title1",
"author": "author1",
"users": [
{
"id": 1,
"name": "Isidro"
},
{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 3,
"name": "Trinidad"
}
]
},
{
"title": "title2",
"author": "author2",
"users": [
{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 5,
"name": "Beatriz"
},
{
"id": 6,
"name": "Rosario"
}
]
},
What I am trying to do, 2 things:
First:
when I click on a user name in the HTML, I want to match the name clicked with the same user name in all the objects it is present in.
Second:
display the title of the books this user name is present in.
For example: when I click on Jose Miguel I want to see the 2 books he has read.
At the moment I have this:
var btnUser = document.querySelectorAll(".individualUsers");
for (var i = 0; i < btnUser.length; i++) {
btnUser[i].addEventListener("click", function() {
var clickedUser = this.innerText
var userBooks = books
.filter(x => x.users.name.indexOf(clickedUser) > -1)
.map(x => ` <li>${x.title}</li> <li>${x.author}</li>`);
console.log(clickedUser);
});
}
My problem is x.users.name.indexOf(clickedUser)is not accessing the user name.
You need to search inside the users array as well, one neat way is to do so with Array.some that return true if some of the conditional is true.
const books = [{
"title": "title1",
"author": "author1",
"users": [{
"id": 1,
"name": "Isidro"
},
{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 3,
"name": "Trinidad"
}
]
},
{
"title": "title2",
"author": "author2",
"users": [{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 5,
"name": "Beatriz"
},
{
"id": 6,
"name": "Rosario"
}
]
}
];
const clickedUser = 'Jose Miguel';
var userBooks = books
.filter(x => x.users.some(user => user.name.indexOf(clickedUser) > -1));
console.log(userBooks);

Categories