Convert polyhierarchy parent-child relationship to array (tree) - javascript or jquery - javascript

var data = [
{
"text": "BEHIND A COMMON MEAL: POLYPHENOLS IN FOOD ",
"id": "445",
"parentid": ""
},
{
"text": "2.2 First Course: Pasta With Tomato Sauce (Polyphenols in Wheat Bran and Tomato Byproducts)",
"id": "441",
"parentid": "445"
},
{
"text": "2.3 A Fresh Side Dish: Mixed Salad (Polyphenols From Fennel, Carrot)",
"id": "442",
"parentid": "445"
},
{
"text": "hello mr.sujai",
"id": "448",
"parentid": "445"
},
{
"text": "polyhierarchy",
"id": "449",
"parentid": "445"
},
{
"text": "INTRODUCTION",
"id": "452",
"parentid": ""
},
{
"text": "1.2 The Tight Biochemical Connection Between Vegetables and Their Byproducts",
"id": "440",
"parentid": "452"
},
{
"text": "OTHER OFF-THE-MENU MISCELLANEOUS",
"id": "454",
"parentid": ""
},
{
"text": "SOMETHING TO DRINK",
"id": "456",
"parentid": ""
},
{
"text": "3.1 Orange Juice (Polyphenols From Orange Byproducts)",
"id": "443",
"parentid": "456"
},
{
"text": "3.2 Wine (Polyphenols From Grape and Wine Byproducts)",
"id": "444",
"parentid": "456"
},
{
"text": "understandings",
"id": "451",
"parentid": "456"
},
{
"text": "Polyphenols",
"id": "453",
"parentid": "451"
},
{
"text": "this is test",
"id": "458",
"parentid": "455"
},
{
"text": "polyhierarchy",
"id": "449",
"parentid": "458"
},
{
"text": "hello",
"id": "447",
"parentid": "449"
},
{
"text": "hi",
"id": "459",
"parentid": "447"
},
{
"text": "polyhierarchy",
"id": "449",
"parentid": "459"
},
{
"text": "testing",
"id": "457",
"parentid": "458"
},
{
"text": "hi test",
"id": "450",
"parentid": "457"
},
{
"text": "speech",
"id": "446",
"parentid": "450"
}]
function jsonTree() {
// Keep a fast lookup dictionary
var dictionary = {};
for (var i = 0; i < data.length; i++) {
dictionary[data[i].id] = data[i];
}
for (var i = 0; i < data.length; i++) {
if (data[i].parentid == 449) {
var test = "";
}
if (data[i].parentid) {
var parent = dictionary[data[i].parentid];
arrData = parent;
if (parent) {
if (!parent.children) {
parent.children = [];
}
parent.children.push(data[i]);
// arrData.children.push(data[i]);
}
}
}
var arrData = [];
for (var i = 0; i < data.length; i++) {
if (data[i].parentid == 455) {
arrData.push(data[i]);
}
}
document.getElementById("test").innerHTML = JSON.stringify(arrData);
return false;
}
polyhierarchy term having different parent.
for (var i = 0; i < data.length; i++) {
dictionary[data[i].id] = data[i];
}
in this place same id is replaced. polyhierarchy having id is 449. when add to dictionary it is replaced.
Tree structure should be
1. BEHIND A COMMON MEAL: POLYPHENOLS IN FOOD
polyhierarchy
2. this is test
polyhierarchy
hello
hi
polyhierarchy
i need array with parent, child relationship.

There are a few mistakes.
You have duplicate id's for your polyhierarchie element. Because you're building a dictionary to lookup your ids, you're overwriting your child element the second/subsequent time you add it to your object.
{
"text": "polyhierarchy",
"id": "449", //<-- duplicate
"parentid": "459"
}
You have non existant parentIds.
{
"text": "SOMETHING TO DRINK",
"id": "456",
"parentid": "455" // <--- doesn't exist
}
The code got a little more complex than anticipated because of those two issues.
function mapData (data) {
//build a dictionary for: id -> [eles]
var map = data.reduce ((obj, ele) => {
obj[ele.id] = [ //let's make the lookup an array, to support multiple elements with the same id
...obj[ele.id] || [], //keep the existing elements or initialize it to an array
{...ele, children: []}
];
return obj
}, {});
return Object.keys (map).reduce ((arr, key) => {
let eles = map [key] || []; //process all elements
eles.forEach (ele => {
let parents = map [ele.parentid] || [];
let parent = parents [0];
if (!parent) {
parent = map [ele.parentid] = {children: [], root: true}
}
parent.children.push (ele);
if (parent.root && !~arr.indexOf (parent)) arr.push (parent);
});
return arr;
},[])
}
console.log (mapData (data))

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.

Remove Null value when delete a json portion using javascript

I am having an json object below. I want to delete a part if the question value is empty. So according to below json I need to delete the id=7602 portion.
[ {
"id": 9333,
"component": "question_pool",
"sub_comp_arr": [
{
"id": 7769,
"component": "question",
"sub_comp_arr": [
{
"id": 2552,
"component": "question_segment",
"value": "Answer1"
},
{
"id": 1011,
"component": "question_segment",
"value": "Answer2"
},
{
"id": 8691,
"component": "question_segment",
"value": "Answer3"
}
],
"type": "single_choice",
"value": "<p>Question1?</p>\n"
},
{
"id": 7602,
"component": "question",
"sub_comp_arr": [
{
"id": 921,
"component": "question_segment",
"value": ""
}
],
"type": "single_choice",
"value": ""
}
]
},{...}
]
I have implemet the code as below
var y= content_json.content_arr;
var keyCount = Object.keys(y).length;
for (var i = 0; i < keyCount; i++) {
var questionCount = (content_json.content_arr[i]['sub_comp_arr']).length;
for (let j = 0; j < questionCount; j++){
var emptyquestion= ((content_json.content_arr[i]['sub_comp_arr'][j]['value']).trim()).length;
if (emptyquestion===0){
delete (content_json.content_arr[i]['sub_comp_arr'][j]);
}
}
}
But the problem is if I use delete (content_json.content_arr[i]['sub_comp_arr'][j]); It is saving a null value on my Json, Which I don't want. How to achieve it
You could use filter instead.
content_json.content_arr[i].sub_comp_arr = content_json.content_arr[i].sub_comp_arr.filter(q => q.value)

Javascript create 2 arrays from object data

I have some data and I need a loop which creates 2 arrays...
So I first create the 2 arrays:
namelist = [];
countList = [];
{
"id": "622",
"name": "main",
"sub": {
"637": {
"id": "637",
"name": "name 1",
"stats": {
"count": 5
}
},
"638": {
"id": "638",
"name": "name 2",
"stats": {
"count": 10
}
}
}
}
The desired result for this example would be:
For namelist:
['name 1', 'name 2']
For countList:
[5, 10]
How can I do this?
var nameList = [];
var countList = [];
var myObj =
{
"id": "622",
"name": "main",
"sub": {
"637": {
"id": "637",
"name": "name 1",
"stats": {
"count": 5
}
},
"638": {
"id": "638",
"name": "name 2",
"stats": {
"count": 10
}
}
}
};
for(var key in myObj.sub){
nameList.push(myObj.sub[key].name);
countList.push(myObj.sub[key].stats.count);
}
console.log(nameList);
console.log(countList);
for(var key in obj.sub){
nameList.push(obj.sub[key].name);
countList.push(obj.sub[key].stats.count;
}
Object.keys may help you to walk through object properties. Example related to your object:
var namelist = [],
countList = [],
obj = {
"id": "622",
"name": "main",
"sub": {
"637": {
"id": "637",
"name": "name 1",
"stats": {
"count": 5
}
},
"638": {
"id": "638",
"name": "name 2",
"stats": {
"count": 10
}
}
}
};
Object.keys(obj.sub).forEach(function(item) {
namelist.push(obj.sub[item].name);
countList.push(obj.sub[item].stats.count);
});
console.log(namelist, countList);
Working example: https://jsfiddle.net/ry0zqweL/
Obviously, you can optimise it in many ways. It's just illustrating one of the many solutions.

how to append next next level json data into tree view structure

I want to append json data to bring tree view structure. Initially I had created static tree view this is my fiddle code with json tree view: https://jsfiddle.net/ak3zLzgd/6/
Here I have challenges to append three level level json data instead of static html code.
Exactly inside retailer digital marketing > sub-ToI > semi-sub-TOI > super-sub-TOI all the thirditems json array is appending ti first value only . For more info check this fiddle: https://jsfiddle.net/ak3zLzgd/6/
var json = {
"category": [{
"title": "Customer Satisfaction",
"id": "nnanet:category/certified-pre-owned",
"items": [{
"title": "Bulletins",
"id": "nnanet:category/customer-satisfaction/bulletins",
"thirditems": [{
"title": "TOI",
"id": "nnanet:category/retailer-digital-marketing/toi"
}, {
"title": "TOI",
"id": "nnanet:category/retailer-digital-marketing/toi"
}]
}, {
"title": "Consumer Affairs",
"id": "nnanet:category/customer-satisfaction/consumer-affairs"
}, {
"title": "Loyalty",
"id": "nnanet:category/customer-satisfaction/loyalty",
"thirditems": [{
"title": "TOI",
"id": "nnanet:category/retailer-digital-marketing/toi"
}, {
"title": "TOI",
"id": "nnanet:category/retailer-digital-marketing/toi"
}]
}]
}, {
"title": "Retailer Digital Marketing",
"id": "nnanet:category/retailer-digital-marketing",
"items": [{
"title": "TOI",
"id": "nnanet:category/retailer-digital-marketing/toi",
"thirditems": [{
"title": "TOI",
"id": "nnanet:category/retailer-digital-marketing/toi"
}, {
"title": "TOI",
"id": "nnanet:category/retailer-digital-marketing/toi"
}]
}, {
"title": "Basics",
"id": "nnanet:category/retailer-digital-marketing/reference-guide/basics"
}, {
"title": "International",
"id": "nnanet:category/retailer-digital-marketing/international"
}]
}, {
"title": "Finance Today",
"id": "nnanet:category/customer-satisfaction/bulletins/finance-today",
"items": [{
"title": "TOI",
"id": "nnanet:category/retailer-digital-marketing/toi",
"thirditems": [{
"title": "TOI",
"id": "nnanet:category/retailer-digital-marketing/toi"
}, {
"title": "TOI",
"id": "nnanet:category/retailer-digital-marketing/toi"
}]
}, {
"title": "Basics",
"id": "nnanet:category/retailer-digital-marketing/reference-guide/basics"
}, {
"title": "International",
"id": "nnanet:category/retailer-digital-marketing/international"
}]
}, {
"title": "Annual",
"id": "nnanet:category/customer-satisfaction/bulletins/finance-today/revenue/annual",
"items": [{
"title": "TOI",
"id": "nnanet:category/retailer-digital-marketing/toi"
}, {
"title": "Basics",
"id": "nnanet:category/retailer-digital-marketing/reference-guide/basics"
}, {
"title": "International",
"id": "nnanet:category/retailer-digital-marketing/international"
}]
}]
};
function expander(){
var tree = document.querySelectorAll('ul.tree a:not(:last-child)');
for(var i = 0; i < tree.length; i++){
tree[i].addEventListener('click', function(e) {
var element = e.target.parentElement; //actually this is just the elem itself
var parent = element.parentElement
var opensubs = parent.querySelectorAll(':scope .open');
console.log(opensubs);
var classList = element.classList;
if(opensubs.length !=0) {
for(var i = 0; i < opensubs.length; i++){
opensubs[i].classList.remove('open');
}
}
classList.add('open');
});
}
}
$(function(){
var tree = $("ul.tree");
$.each(json.category,function(category){
var categoryValue = json.category[category];
tree.append('<li>'+categoryValue.title+'<ul></ul></li>');
var el = tree.children("li").children("ul");
$.each(categoryValue.items,function(itemId){
var item = categoryValue.items[itemId];
$(el[category]).append('<li>'+item.title+'</li>');
if(item.thirditems){
$(el[category]).children("li").append('<ul></ul>');
var el1 = el.children("li").children("ul");
$.each(item.thirditems,function(thirdItemId){
var thirdItem = item.thirditems[thirdItemId];
console.log(el1[itemId]);
$(el1[itemId]).append('<li>'+thirdItem.title+'<ul></ul></li>');
});
}
});
});
expander();
});
Output : check this fiddle : https://jsfiddle.net/ak3zLzgd/6/

How to select json item from the array

From the below JSON, how can I retrieve title from the note and notes using a for loop and ajax to retrieve?
{
"infos": {
"info": [
{
"startYear": "1900",
"endYear": "1930",
"timeZoneDesc": "daweerrewereopreproewropewredfkfdufssfsfsfsfrerewrBlahhhhh..",
"timeZoneID": "1",
"note": {
"notes": [
{
"id": "1",
"title": "Mmm"
},
{
"id": "2",
"title": "Wmm"
},
{
"id": "3",
"title": "Smm"
}
]
},
"links": [
{ "id": "1", "title": "Red House", "url": "http://infopedia.nl.sg/articles/SIP_611_2004-12-24.html" },
{ "id": "2", "title": "Joo Chiat", "url": "http://www.the-inncrowd.com/joochiat.htm" },
{ "id": "3", "title": "Bake", "url": "https://thelongnwindingroad.wordpress.com/tag/red-house-bakery" }
]
}
I tried out the code below but it doesn't work - it either says:
is null
not an object
length is null
r not an object
var detail = eval(xmlhttprequest.responseText)
var rss = detail.infos.info
for(var i = 0; i<rss.length; i++)
startyear += rss[i].startyear
Use
for (i = 0; i < 3; i++) {
alert(JSON.infos.info[0].note.notes[i].title);
}
TRY IT HERE: JSFIDDLE WORKING EXAMPLE
BTW your JSON is not valid. Use this JSON:
var JSON = {
"infos": {
"info": [
{
"startYear": "1900",
"endYear": "1930",
"timeZoneDesc": "daweerrewereopreproewropewredfkfdufssfsfsfsfrerewrBlahhhhh..",
"timeZoneID": "1",
"note": {
"notes": [
{
"id": "1",
"title": "Mmm"
},
{
"id": "2",
"title": "Wmm"
},
{
"id": "3",
"title": "Smm"
}
]
},
"links": [
{
"id": "1",
"title": "Red House",
"url": "http://infopedia.nl.sg/articles/SIP_611_2004-12-24.html"
},
{
"id": "2",
"title": "Joo Chiat",
"url": "http://www.the-inncrowd.com/joochiat.htm"
},
{
"id": "3",
"title": "Bake",
"url": "https://thelongnwindingroad.wordpress.com/tag/red-house-bakery"
}
]
}
]
}
}
EDIT:
Here is what you want:
var infoLength= JSON.infos.info.length;
for (infoIndex = 0; infoIndex < infoLength; infoIndex++) {
var notesLength= JSON.infos.info[infoIndex].note.notes.length;
for (noteIndex = 0; noteIndex < notesLength; noteIndex++) {
alert(JSON.infos.info[infoIndex].note.notes[noteIndex].title);
}
}
Putting your json into an var called obj, use the following:
obj.infos.info[0].note.notes[0].title
http://jsfiddle.net/Znq34/
Well the "path" to the JSON notes array-like object is:
json.infos.info[0].note.notes;
So you could do something like:
var notes = json.infos.info[0].note.notes;
var titles = [];
for (var i = 0, len = notes.length; i < len; i++)
{
titles.push(notes[i].title);
}
alert('titles is: ' + titles.join(', '));
Fiddle: http://jsfiddle.net/garreh/uDxqD/
Are you using jQuery? ;-)
// Assuming your using "success" in ajax response
success: function(json)
{
var titles = $(json.infos.info[0].note.notes).map(function() {
return this.title;
}).get();
alert(titles.join(', '));
}
First count the length of notes
var len = jsonobject.infos.info.note.notes.length;
Then loops through and get
var title = jsonobject.infos.info.note.notes[i].title;

Categories