Related
I want to iterate the tree and need to get the id of all the nodes which has the children in string array. while looping it is just returning me the record but doesn't extract the name of the node.
e.g const result = ['root', 'USER', 'ROLE', 'DASHBOARD', 'BRAND', 'COMPANY'];
{
"id": "root",
"name": "Roles and Permissions",
"children": [
{
"id": "USER",
"name": "USER",
"children": [
{
"id": "1",
"name": "VIEW"
},
{
"id": "2",
"name": "CREATE"
},
{
"id": "3",
"name": "EDIT"
}
]
},
{
"id": "ROLE",
"name": "ROLE",
"children": [
{
"id": "8",
"name": "VIEW"
},
{
"id": "9",
"name": "CREATE"
},
{
"id": "10",
"name": "EDIT"
},
{
"id": "11",
"name": "DELETE"
}
]
},
{
"id": "DASHBOARD",
"name": "DASHBOARD",
"children": [
{
"id": "BRAND",
"name": "BRAND",
"children": [
{
"id": "52",
"name": "VIEW"
},
{
"id": "53",
"name": "CREATE"
},
{
"id": "54",
"name": "EDIT"
},
{
"id": "55",
"name": "DELETE"
}
]
},
{
"id": "COMPANY",
"name": "COMPANY",
"children": [
{
"id": "56",
"name": "VIEW"
},
{
"id": "57",
"name": "CREATE"
},
{
"id": "58",
"name": "EDIT"
},
{
"id": "59",
"name": "DELETE"
}
]
}
]
}
]
}
I tried various looping method to get the list, e.g. but not returning the exact name of the node.
function getParent(nodes) {
if(Array.isArray(nodes.children)) {
return nodes.children.map((node) => getParent(node));
}
return nodes.name;
}
You can store the resp in an array and return that array.
const q = {
"id": "root",
"name": "Roles and Permissions",
"children": [
{
"id": "USER",
"name": "USER",
"children": [
{
"id": "1",
"name": "VIEW"
},
{
"id": "2",
"name": "CREATE"
},
{
"id": "3",
"name": "EDIT"
}
]
},
{
"id": "ROLE",
"name": "ROLE",
"children": [
{
"id": "8",
"name": "VIEW"
},
{
"id": "9",
"name": "CREATE"
},
{
"id": "10",
"name": "EDIT"
},
{
"id": "11",
"name": "DELETE"
}
]
},
{
"id": "DASHBOARD",
"name": "DASHBOARD",
"children": [
{
"id": "BRAND",
"name": "BRAND",
"children": [
{
"id": "52",
"name": "VIEW"
},
{
"id": "53",
"name": "CREATE"
},
{
"id": "54",
"name": "EDIT"
},
{
"id": "55",
"name": "DELETE"
}
]
},
{
"id": "COMPANY",
"name": "COMPANY",
"children": [
{
"id": "56",
"name": "VIEW"
},
{
"id": "57",
"name": "CREATE"
},
{
"id": "58",
"name": "EDIT"
},
{
"id": "59",
"name": "DELETE"
}
]
}
]
}
]
}
let result = []
function r(nodes){
if(Array.isArray(nodes.children)){
result.push(nodes.name);
nodes.children.map((c) => r(c))
return result;
}
return result;
}
console.log(r(q))
You can simply use a recursive function. Here ids is an array. You can initialize it before calling the function. Call this function in your getting IDs method.
const getIdFromNodesWithChild = (node) => {
if (node.children != undefined){
ids.push(node.id)
const children_list = node.children
children_list.forEach( new_child => getIdFromNodesWithChild(new_child))
}}
caller function
const returnIds = (tree) => {
ids = []
getIdFromNodesWithChild(tree)
return (ids)
}
result : ['root', 'USER', 'ROLE', 'DASHBOARD', 'BRAND', 'COMPANY']
I have a Objects of an array of objects as given below. I am trying to filter out each object within the array where is quantity is greater than 0 and drop it in a new variable. So via lodash I tried to use _.filter within _.(myArr).forEach. But this always returns an empty array. The console.log within _.filter shows quantity as it is but it doesn't return any value based on the condition. Am I using it in a proper way here or is there any other way I can use this to filter out?
var data = [
[{
"aid": "1",
"desc": "Desc 1",
"name": "Name 1",
"quantity": 1
}, {
"aid": "2",
"desc": "Desc 2",
"name": "Name 2",
"quantity": 1
}, {
"aid": "3",
"desc": "Desc 3",
"name": "Name 3",
"quantity": 0
}],
[{
"aid": "4",
"desc": "Desc 4",
"name": "Name 4",
"quantity": 0
}, {
"aid": "5",
"desc": "Desc 5",
"name": "Name 5",
"quantity": 1
}],
[{
"aid": "6",
"desc": "Desc 6",
"name": "Name 6",
"quantity": 0
}, {
"aid": "7",
"desc": "Desc 7",
"name": "Name 7",
"quantity": 0
}]
];
var filtered;
_(data).forEach((d) => {
filtered = _.filter(d, (o) => {
return o.quantity > 0;
});
});
console.log(filtered);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.0/lodash.min.js"></script>
You are overwriting filtered in each iteration, so its value will represent only what happened in the last iteration of the forEach loop.
You should instead accumulate the individual results into an array, for instance with push and the spread syntax:
var filtered = [];
... and in the loop:
filtered.push(..._.filter(d, (o) => o.quantity > 0);
Note that you can do this in vanilla JavaScript, using array methods like reduce and filter:
var data = [ [{ "aid": "1", "desc": "Desc 1", "name": "Name 1", "quantity": 1 }, { "aid": "2", "desc": "Desc 2", "name": "Name 2", "quantity": 1 }, { "aid": "3", "desc": "Desc 3", "name": "Name 3", "quantity": 0 }], [{ "aid": "4", "desc": "Desc 4", "name": "Name 4", "quantity": 0 }, { "aid": "5", "desc": "Desc 5", "name": "Name 5", "quantity": 1 }], [{ "aid": "6", "desc": "Desc 6", "name": "Name 6", "quantity": 0 }, { "aid": "7", "desc": "Desc 7", "name": "Name 7", "quantity": 0}]];
var filtered = data.reduce(
(filtered, d) => filtered.concat(d.filter( o => o.quantity > 0 )),
[]
);
console.log(filtered);
.as-console-wrapper { max-height: 100% !important; top: 0; }
using native js:
let filtered = data.reduce((a, e) => a.concat(e)).filter(x => x.quantity > 0);
Or alternatively you can use reduce
var output = data.reduce(
( acc, c ) => acc.concat( c.filter(
s => s.quantity > 0 ) ) //filter out quantities > 0
,[]); //initialize accumulator to []
Demo
var data = [
[{
"aid": "1",
"desc": "Desc 1",
"name": "Name 1",
"quantity": 1
}, {
"aid": "2",
"desc": "Desc 2",
"name": "Name 2",
"quantity": 1
}, {
"aid": "3",
"desc": "Desc 3",
"name": "Name 3",
"quantity": 0
}],
[{
"aid": "4",
"desc": "Desc 4",
"name": "Name 4",
"quantity": 0
}, {
"aid": "5",
"desc": "Desc 5",
"name": "Name 5",
"quantity": 1
}],
[{
"aid": "6",
"desc": "Desc 6",
"name": "Name 6",
"quantity": 0
}, {
"aid": "7",
"desc": "Desc 7",
"name": "Name 7",
"quantity": 0
}]
];
var output = data.reduce( ( acc, c ) => acc.concat( c.filter( s => s.quantity > 0 ) ) ,[]);
console.log(output);
I have below JavaScript with n level children and want to search for id and if any of item from has matching id than need to return object from root to matching item.
I want to return entire hierarchy of found item from root till object with it's children.
I tried with lodash and underscore and could not find easy solution.
input: {
"children": [{
"name": "Home",
"title": "Home",
"id": "home1",
"children": []
},
{
"name": "BUSINESS AND ROLE SPECIFIC",
"title": "BUSINESS AND ROLE SPECIFIC",
"id": "BAR1",
"children": [{
"name": "Global Businesses",
"title": "Global Businesses",
"id": "GB1",
"children": [{
"name": "Commercial Banking",
"title": "Commercial Banking",
"id": "CB1",
"children": [{
"name": "FLAGSHIP PROGRAMMES",
"title": "FLAGSHIP PROGRAMMES",
"id": "FG1",
"children": []
}]
}]
}]
},
{
"name": "RISK MANAGEMENT",
"title": "RISK MANAGEMENT",
"id": "RM1",
"children": []
}
]
}
Search: {
id: 'FG1'
}
return :{
"name": "BUSINESS AND ROLE SPECIFIC",
"title": "BUSINESS AND ROLE SPECIFIC",
"id": "BAR1",
"children": [{
"name": "Global Businesses",
"title": "Global Businesses",
"id": "GB1",
"children": [{
"name": "Commercial Banking",
"title": "Commercial Banking",
"id": "CB1",
"children": [{
"name": "FLAGSHIP PROGRAMMES",
"title": "FLAGSHIP PROGRAMMES",
"id": "FG1",
"children": [{}]
}]
}]
}]
}
You could use this function:
function findChild(obj, condition) {
if (Object.entries(condition).every( ([k,v]) => obj[k] === v )) {
return obj;
}
for (const child of obj.children || []) {
const found = findChild(child, condition);
// If found, then add this node to the ancestors of the result
if (found) return Object.assign({}, obj, { children: [found] });
}
}
// Sample data
var input = { "children": [{ "name": "Home", "title": "Home", "id": "home1", "children": [] }, { "name": "BUSINESS AND ROLE SPECIFIC", "title": "BUSINESS AND ROLE SPECIFIC", "id": "BAR1", "children": [{ "name": "Global Businesses", "title": "Global Businesses", "id": "GB1", "children": [{ "name": "Commercial Banking", "title": "Commercial Banking", "id": "CB1", "children": [{ "name": "FLAGSHIP PROGRAMMES", "title": "FLAGSHIP PROGRAMMES", "id": "FG1", "children": [] }] }] }] }, { "name": "RISK MANAGEMENT", "title": "RISK MANAGEMENT", "id": "RM1", "children": [] } ]},
search = { id: 'FG1' };
console.log(findChild(input, search));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use this also for searching with multiple conditions, which must be true at the same time:
search = { "name": "Global Businesses", "title": "Global Businesses" };
... would give you the object that has the specified name and title.
Follow-up question
You asked in comments:
Is there way to supply number to not remove children for given node in input. like,
const donotRemoveChildNode = 2;
console.log(findChild(input, search, donotRemoveChildNode ));
...so it will not remove that specific node's children if it matches condition?
Here, if we search for { id: 'FG1'} and supply donotRemoveChildNode = 2, it would not remove the first level children for "Commercial banking".
I would say the donotRemoveChildNode would have to be 3, as there are three levels of children arrays in the ancestor-hierarchy of the "Commercial banking" node. A value of 0 would show the first level children of the top-most children property.
Here is how that extra argument would work -- I added some records to the data to illustrate the difference in the output:
function findChild(obj, condition, removeChildNodesBefore = Infinity) {
if (Object.entries(condition).every( ([k,v]) => obj[k] === v )) {
return obj;
}
for (const child of obj.children || []) {
let found = findChild(child, condition, removeChildNodesBefore - 1);
if (found) {
return Object.assign({}, obj, {
children: removeChildNodesBefore <= 0
? obj.children.map( sibling =>
sibling == child ? found
: Object.assign({}, sibling, {children: []})
)
: [found]
});
}
}
}
var input = { "children": [{ "name": "Home", "title": "Home", "id": "home1", "children": [] }, { "name": "BUSINESS AND ROLE SPECIFIC", "title": "BUSINESS AND ROLE SPECIFIC", "id": "BAR1", "children": [{ "name": "Global Businesses", "title": "Global Businesses", "id": "GB1", "children": [{ "name": "test", "title": "test", "id": "xxx", "children": [{ "name": "testDeep", "title": "test", "id": "deep", "children": []}]}, { "name": "Commercial Banking", "title": "Commercial Banking", "id": "CB1", "children": [{ "name": "test", "title": "test", "id": "yyy", "children": []}, { "name": "FLAGSHIP PROGRAMMES", "title": "FLAGSHIP PROGRAMMES", "id": "FG1", "children": [] }] }] }] }, { "name": "RISK MANAGEMENT", "title": "RISK MANAGEMENT", "id": "RM1", "children": [] } ]},
search = { id: 'FG1' }
console.log(findChild(input, search, 3));
.as-console-wrapper { max-height: 100% !important; top: 0; }
function getBranch(branches, leaf_id)
{
var result_branch = null;
branches.some(function(branch, idx) {
if (branch.id == leaf_id) {
result_branch = Object.assign({}, branch);
result_branch.children.forEach(function(child, idx) {
delete result_branch.children[idx].children;
});
return true;
} else {
let target_branch = getBranch(branch.children, leaf_id);
if (target_branch) {
result_branch = Object.assign({}, branch);
delete result_branch.children
result_branch.children = [target_branch];
return true;
}
}
return false;
});
return result_branch;
}
console.log(getBranch(input.children, 'GB1'));
One way is to first loop the root children, and then create another function to see if the Id exists in any of it's children.
var data = {
"children": [{
"name": "Home",
"title": "Home",
"id": "home1",
"children": []
},
{
"name": "BUSINESS AND ROLE SPECIFIC",
"title": "BUSINESS AND ROLE SPECIFIC",
"id": "BAR1",
"children": [{
"name": "Global Businesses",
"title": "Global Businesses",
"id": "GB1",
"children": [{
"name": "Commercial Banking",
"title": "Commercial Banking",
"id": "CB1",
"children": [{
"name": "FLAGSHIP PROGRAMMES",
"title": "FLAGSHIP PROGRAMMES",
"id": "FG1",
"children": []
}]
}]
}]
},
{
"name": "RISK MANAGEMENT",
"title": "RISK MANAGEMENT",
"id": "RM1",
"children": []
}
]
};
function hasId( id, data ) {
if (data.id === id) return true;
if (data.children) {
for (const child of data.children) {
if (hasId( id, child)) return true;
}
}
return false;
}
function search( id, data ) {
for (const child of data.children) {
if (hasId(id, child)) return child;
}
return null;
}
console.log(search( "FG1", data ));
So I have 2 arrays:
(from user table)
[{
"id": "123",
"name": "Peter",
"description": "person in the office"
}]
(from department table)
[{
"id": "R1",
"name": "Marketing",
"description": "Yea Marketing"
},
{
"id": "R2",
"name": "Sales",
"description": "More Sales"
}]
what I want to do is combine the two arrays into a single array to look like this:
[{
"user": [{
"id": "123",
"name": "Peter",
"description": "person in the office" }],
"department": [{
"id": "R1",
"name": "Marketing",
"description": "Yea Marketing"
},
{
"id": "R2",
"name": "Sales",
"description": "More Sales"
}]
}]
I know how to concat arrays and push but both ways only merge the data together without allowing me to add in the headers of user and department. If I use concat with strings to add in the headers then I get back [{ "\"user\": [{ \n \"name\":.....
Is there a way I can combine the arrays and add some type of header field?
Is this what you're after?
var user = [{
"id": "123",
"name": "Peter",
"description": "person in the office"
}];
var departments = [{
"id": "R1",
"name": "Marketing",
"description": "Yea Marketing"
},
{
"id": "R2",
"name": "Sales",
"description": "More Sales"
}];
var combined = [{
user: user,
department: departments,
}];
var userArr = [{
"id": "123",
"name": "Peter",
"description": "person in the office"
}];
var deptArr = [{
"id": "R1",
"name": "Marketing",
"description": "Yea Marketing"
},
{
"id": "R2",
"name": "Sales",
"description": "More Sales"
}];
var merged = [];
merged.push({'user':userArr,'department':deptArr});
this is my controller in angularjs
(function(){
"use strict";
angular
.module("testApp")
.controller("testAppCtrl", function($scope , $http){
$http.get('/data/testapp.json').then(function(data){
//$scope.testapps = testapp.data;
console.log(data);
});
});
})();
and i face this error
angular.js:13708 SyntaxError: Unexpected token p in JSON at position 130
how can i fix it?
Your json file has invalid code.You are missing quots around posted and contact also in the and extra , is inserted this should be like
[{
"id": "1",
"title": "test1",
"description": "test 1 test 1 test 1 test 1 test 1 ",
"price": "2000",
"posted": "2015-10-24",
"contact": {
"name": "test1 mona",
"phone": "98765678",
"email": "test#gmail.com"
},
"categories": [
"vehicle",
"test"
],
"image": "1.jpg",
"views": "200"
}, {
"id": "2",
"title": "test2",
"description": "test 2 test 2 test 2 test 2 test 2 ",
"price": "2000",
"posted": "2015-10-24",
"contact": {
"name": "test2 mona",
"phone": "98765678",
"email": "test#gmail.com"
},
"categories": [
"vehicle",
"test"
],
"image": "1.jpg",
"views": "200"
}, {
"id": "3",
"title": "test3",
"description": "test 3 test 3 test 3 test 3 test 3 ",
"price": "3000",
"posted": "2015-10-24",
"contact": {
"name": "test3 mona",
"phone": "98765678",
"email": "test#gmail.com"
},
"categories": [
"vehicle",
"test"
],
"image": "1.jpg",
"views": "100"
}, {
"id": "4",
"title": "test4",
"description": "test 4 test 4 test 4 test 4 test 4 ",
"price": "4000",
"posted": "2015-10-24",
"contact": {
"name": "test4 mona",
"phone": "98765678",
"email": "test#gmail.com"
},
"categories": [
"vehicle",
"test"
],
"image": "1.jpg",
"views": "40"
}, {
"id": "5",
"title": "test5",
"description": "test 5 test 5 test 5 test 5 test 5 ",
"price": "5000",
"posted": "2015-10-24",
"contact": {
"name": "test5 mona",
"phone": "98765678",
"email": "test#gmail.com"
},
"categories": [
"vehicle",
"test"
],
"image": "1.jpg",
"views": "290"
}, {
"id": "6",
"title": "test6",
"description": "test 6 test 6 test 6 test 6 test 6 ",
"price": "6000",
"posted": "2015-10-24",
"contact": {
"name": "test6 mona",
"phone": "98765678",
"email": "test#gmail.com"
},
"categories": [
"vehicle",
"test"
],
"image": "1.jpg",
"views": "10"
}]