I have a JavaScript object which contains lots of properties. I need to create another similar hierarchy but I only need few properties.
[
{
_id: "559d0fcdd791e5c452345e80",
name: "Books",
lastUpdated: "2015-07-08T11:55:57.891Z",
body: "",
children: [
{
_id: "559d0fd9d791e5c452345e81",
name: "web apps",
__v: 2,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:56:09.356Z",
body: "",
children: [
{
_id: "559d0fe9d791e5c452345e83",
name: ".net",
__v: 1,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:56:25.139Z",
body: "",
children: [
{
_id: "559d0ff2d791e5c452345e84",
name: "asp.net",
__v: 0,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:56:34.306Z",
body: "",
children: [
],
parent: "559d0fe9d791e5c452345e83",
description: ""
}
],
parent: "559d0fd9d791e5c452345e81",
description: ""
},
{
_id: "559d0ffad791e5c452345e85",
name: "java",
__v: 0,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:56:42.663Z",
body: "",
children: [
],
parent: "559d0fd9d791e5c452345e81",
description: ""
}
],
parent: "559d0fcdd791e5c452345e80",
description: ""
},
{
_id: "559d0fe0d791e5c452345e82",
name: "db",
__v: 2,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:56:16.436Z",
body: "",
children: [
{
_id: "559d1006d791e5c452345e86",
name: "SQL server",
__v: 0,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:56:54.289Z",
body: "",
children: [
],
parent: "559d0fe0d791e5c452345e82",
description: ""
},
{
_id: "559d101ad791e5c452345e87",
name: "NO SQL",
__v: 1,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:57:14.988Z",
body: "",
children: [
{
_id: "559d1025d791e5c452345e88",
name: "MongoDB",
__v: 0,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:57:25.044Z",
body: "",
children: [
],
parent: "559d101ad791e5c452345e87",
description: ""
}
],
parent: "559d0fe0d791e5c452345e82",
description: ""
}
],
parent: "559d0fcdd791e5c452345e80",
description: ""
}
],
parent: null,
description: "Some books"
}
]
From this I need to create a hierarchy like this:
[{
text: 'books',
nodes: [{
text:'web apps',
nodes:[{
text: '.net',
nodes:[{
text:'asp.net',
nodes:[]
}]
},{
text: 'java',
nodes:[]
}]
},{
text: 'DB',
nodes: [{
text: 'SQL Server'
},{
text: 'NO SQL',
nodes:[{
text: 'MongoDB'
}]
}]
}]
}]
I am trying to create a recursive loop but not sure how to add child nodes. How can I get the desired result.
You need a recursive function. This one is constructed for your specific data input:
function reduce (input, output) {
output = [];
$.each(input, function(key, val) {
output[key] = {};
output[key].text = val.name;
output[key].nodes = reduce(val.children);
});
return output;
}
and it is called with output = reduce(input);
Here's a snippet:
input = [
{
_id: "559d0fcdd791e5c452345e80",
name: "Books",
lastUpdated: "2015-07-08T11:55:57.891Z",
body: "",
children: [
{
_id: "559d0fd9d791e5c452345e81",
name: "web apps",
__v: 2,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:56:09.356Z",
body: "",
children: [
{
_id: "559d0fe9d791e5c452345e83",
name: ".net",
__v: 1,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:56:25.139Z",
body: "",
children: [
{
_id: "559d0ff2d791e5c452345e84",
name: "asp.net",
__v: 0,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:56:34.306Z",
body: "",
children: [
],
parent: "559d0fe9d791e5c452345e83",
description: ""
}
],
parent: "559d0fd9d791e5c452345e81",
description: ""
},
{
_id: "559d0ffad791e5c452345e85",
name: "java",
__v: 0,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:56:42.663Z",
body: "",
children: [
],
parent: "559d0fd9d791e5c452345e81",
description: ""
}
],
parent: "559d0fcdd791e5c452345e80",
description: ""
},
{
_id: "559d0fe0d791e5c452345e82",
name: "db",
__v: 2,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:56:16.436Z",
body: "",
children: [
{
_id: "559d1006d791e5c452345e86",
name: "SQL server",
__v: 0,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:56:54.289Z",
body: "",
children: [
],
parent: "559d0fe0d791e5c452345e82",
description: ""
},
{
_id: "559d101ad791e5c452345e87",
name: "NO SQL",
__v: 1,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:57:14.988Z",
body: "",
children: [
{
_id: "559d1025d791e5c452345e88",
name: "MongoDB",
__v: 0,
media: {
images: [
]
},
lastUpdated: "2015-07-08T11:57:25.044Z",
body: "",
children: [
],
parent: "559d101ad791e5c452345e87",
description: ""
}
],
parent: "559d0fe0d791e5c452345e82",
description: ""
}
],
parent: "559d0fcdd791e5c452345e80",
description: ""
}
],
parent: null,
description: "Some books"
}
]
function reduce (input, output) {
output = [];
$.each(input, function(key, val) {
output[key] = {};
output[key].text = val.name;
output[key].nodes = reduce(val.children);
});
return output;
}
output = reduce(input);
$('div').text(JSON.stringify(output));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div></div>
Related
i want to loop through array of objects and check for a particular property and add a new property "disabled" to the array.
below is the array of objects
const arr_obj = [
{
id: "1",
name: "name1",
type: "type2",
children: [
{
id: "2",
name: "name2",
type: "type4",
children: [
{
id: "3",
name: "name3",
type: "type5",
},
},
{
id: "4",
name: "name4",
type: "type3",
children: [
{
id: "5",
name: "name5",
type: "type4",
children: [],
},
],
},
id: "6",
name: "name6",
type: "type3",
children: [
{
id: "7",
name: "name7",
type: "type4",
children: [],
},
],
}
},
.....//similar objects
];
so from above array of objects i want to check for each object if type === type2 and if type2 then add property disabled: false if not disabled: true.
below is what i have tried
const new_obj = React.useMemo(() => {
return arr_obj.map((arr) => ({
...arr,
disabled: arr?.type !== "type2" ? true : false,
}));
}, [arr_obj]);
this adds disabled property only to outer object it doesnt add to children object.
output with above snippet is like below,
const new_arr = [
{
id: "1",
name: "name1",
type: "type2",
disabled: false,
children: [
{
id: "2",
name: "name2",
type: "type4",
children: [
{
id: "3",
name: "name3",
type: "type5",
},
},
{
id: "4",
name: "name4",
type: "type3",
children: [
{
id: "5",
name: "name5",
type: "type4",
children: [],
},
],
},
id: "6",
name: "name6",
type: "type3",
children: [
{
id: "7",
name: "name7",
type: "type4",
children: [],
},
],
}
},
.....//similar objects
];
expected output is like below,
const new_arr = [
{
id: "1",
name: "name1",
type: "type2",
disabled: false,
children: [
{
id: "2",
name: "name2",
type: "type4",
disabled: true,
children: [
{
id: "3",
name: "name3",
type: "type5",
disabled: true,
},
},
{
id: "4",
name: "name4",
type: "type3",
disabled: true,
children: [
{
id: "5",
name: "name5",
type: "type4",
disabled: true,
children: [],
},
],
},
id: "6",
name: "name6",
type: "type3",
disabled: true
children: [
{
id: "7",
name: "name7",
type: "type4",
disabled: true,
children: [],
},
],
}
},
.....//similar objects
];
How can i fix the above snippet such that it adds disabled property to children too. could someone help me with this. thanks.
EDIT:
tried answer is like below,
function loop_children(children) {
if (!children || children.lengh <=0) {
return;
} else {
return children.map((child) => {
...child,
disabled: child?.type !== "type2" ? true : false,
children: loop_children(children)
})
};
}
}
return arr_obj.map((arr) => ({
...arr,
disabled: arr?.type !== "type2" ? true : false,
children: loop_children(arr.children) //seems like a problem here in adding children field again
}));
but this adds children array under children again.
This code doesnt work. it adds field disabled to children but also adds children within children.
could someone help me with this. thanks.
Not sure why all the others are mapping, just alter the object with a simple recursive call when it has a children property.
const arr_obj = [{
id: "1",
name: "name1",
type: "type2",
children: [{
id: "2",
name: "name2",
type: "type4",
children: [{
id: "3",
name: "name3",
type: "type5",
}, ]
}, ]
}];
const disableEnableObj = (arr, type) => {
arr.forEach(obj => {
obj.disabled = obj.type !== type;
obj.children && disableEnableObj(obj.children, type);
});
}
disableEnableObj(arr_obj, 'type2');
console.log(arr_obj);
You have to loop through the children too. It should look something like this:
function loop_children(children) {
return children.map((child) => {
...child,
disabled: child?.type !== "type2" ? true : false,
children: loop_children(children)
})
}
return arr_obj.map((arr) => ({
...arr,
disabled: arr?.type !== "type2" ? true : false,
children: loop_children(children)
}));
I can't figure out how to properly use .filter() to find an object in an Array by searching for a value in its nested Array.
I have the following data:
const orders = [
{
id: 1,
items: [
{
itemId: "abc",
},
{
itemId: "def",
},
],
},
{
id: 2,
items: [
{
itemId: "jkl",
},
{
itemId: "mno",
},
],
},
{
id: 3,
items: [
{
itemId: "abc",
},
{
itemId: "xyz",
},
],
},
];
I have the needed itemId: "abc" which I need to use to find all the objects that have items that also have the Id of "abc", so that the result is this:
[
{
id: 1,
items: [
{
itemId: "abc",
},
{
itemId: "def",
},
],
},
{
id: 3,
items: [
{
itemId: "abc",
},
{
itemId: "xyz",
},
],
},
]
So far, I've tried the following:
orders &&
orders.filter((order) => {
return order.items.filter((item) => item.itemId === "abc");
});
But it doesn't seem to work. What am I missing here?
Chris G beat me to it in the comments but he is right, you need to use order.items.some in your inner function:
const orders = [{
id: 1,
items: [{
itemId: "abc",
},
{
itemId: "def",
},
],
},
{
id: 2,
items: [{
itemId: "jkl",
},
{
itemId: "mno",
},
],
},
{
id: 3,
items: [{
itemId: "abc",
},
{
itemId: "xyz",
},
],
},
]
var ans = orders.filter((order) => {
return order.items.some((item) => item.itemId === "abc");
});
console.log(ans)
const orders = [{
id: 1,
items: [{
itemId: "abc",
},
{
itemId: "def",
},
],
},
{
id: 2,
items: [{
itemId: "jkl",
},
{
itemId: "mno",
},
],
},
{
id: 3,
items: [{
itemId: "abc",
},
{
itemId: "xyz",
},
],
},
];
const result = orders.filter(order =>
order.items.find(item => item.itemId === 'abc') !== undefined
)
console.log(result);
I have array of comments and their replies like this:
[
{
commentId: "5efd85d5b2eff7063b8ec802",
description: "some comment description",
isAnonymous: false,
createdAt: "2020-07-02T06:59:33.317Z",
currentUserLiked: 0,
likes: 0,
user: {
firstName: "ar",
lastName: "ar",
email: "test#email.com",
username: "sami",
isVerified: false,
},
children: [
{
commentId: "5efd86b7b2eff7063b8ec803",
parentId: "5efd85d5b2eff7063b8ec802",
description: "some comment description",
isAnonymous: false,
createdAt: "2020-07-02T07:03:19.405Z",
currentUserLiked: 0,
likes: 0,
user: {
firstName: "ar",
lastName: "ar",
email: "test#email.com",
username: "sami",
isVerified: false,
},
children: [
{
commentId: "5efd89c4b2eff7063b8ec805",
parentId: "5efd86b7b2eff7063b8ec803",
description: "Child of Child",
isAnonymous: false,
createdAt: "2020-07-02T07:16:20.717Z",
currentUserLiked: 0,
likes: 0,
user: {
firstName: "ar",
lastName: "ar",
email: "test#email.com",
username: "sami",
isVerified: false,
},
children: [],
},
],
},
{
commentId: "5efd8996b2eff7063b8ec804",
parentId: "5efd85d5b2eff7063b8ec802",
description: "Child of Child",
isAnonymous: false,
createdAt: "2020-07-02T07:15:34.341Z",
currentUserLiked: 0,
likes: 0,
user: {
firstName: "ar",
lastName: "ar",
email: "test#email.com",
username: "sami",
isVerified: false,
},
children: [],
},
],
},
];
and I want to show them as all children in same level in react native using flatList.
How can I do this?
Do I understand correctly?:
const comments = [{id: 1, children: [{id: 2, children: [{id: 3, children:[]}]}]}];
const flatComments = (list) => {
return list.flatMap(el => {
const {children, ...out} = el;
return [out, ...flatComments(children)];
});
};
flatComments(comments);
// [{id: 1}, {id: 2}, {id: 3}];
I have a primary parent collection (Projects) and 2 child collections stored as arrays with objects.
Projects
const projects = {
items: [
{
name: "Logo and Branding for Iron Kettle",
skills: [
"579b150756ea2dba79c1f09f",
"579b150756ea2dba79c1f062"
],
solutions: [
"579b150756ea2dba79c1f09e",
"579b150756ea2dba79c1f077"
],
_cid: "579b150756ea2dba79c1efcb",
_id: "579b150756ea2dba79c1f0af"
},
{
name: "Snow shoot for media company",
skills: [
"579b150756ea2dba79c1f072",
"579b150756ea2dba79c1f062"
],
solutions": [
"579b150756ea2dba79c1f09e",
"579b150756ea2dba79c1f071",
],
_cid: "579b150756ea2dba79c1efcb",
_id: "579b150756ea2dba79c1f06a"
}
],
count: 12,
limit: 100,
offset: 0,
total: 12
};
Skills
const skills = {
items: [
{
name: "Logo Design",
_cid: "579b150756ea2dba79c1efdf",
_id: "579b150756ea2dba79c1f09f"
},
{
name: "Brand Research",
_cid: "579b150756ea2dba79c1efdf",
_id: "579b150756ea2dba79c1f072"
},
{
name: "Graphic Design",
_cid: "579b150756ea2dba79c1efdf",
_id: "579b150756ea2dba79c1f062"
}
],
count: 13,
limit: 100,
offset: 0,
total: 13
};
Solutions
const solutions = {
items: [
{
name: "Location research",
_cid: "579b150756ea2dba79c1eff3",
_id: "579b150756ea2dba79c1f09e"
},
{
name: "Complete photo shoot",
_cid: "579b150756ea2dba79c1eff3",
_id: "579b150756ea2dba79c1f071"
},
{
name: "Competition Analysis",
_cid: "579b150756ea2dba79c1eff3",
_id: "579b150756ea2dba79c1f077"
}
],
count: 19,
limit: 100,
offset: 0,
total: 19
};
I need to return a new projects array with the skills and solutions id's populated with the actual object from the relevant array.
This would be the end result of one item the new array.
{
name: "Logo and Branding for Iron Kettle",
skills: [
{
name: "Logo Design",
_cid: "579b150756ea2dba79c1efdf",
_id: "579b150756ea2dba79c1f09f"
},
{
name: "Graphic Design",
_cid: "579b150756ea2dba79c1efdf",
_id: "579b150756ea2dba79c1f062"
}
],
solutions: [
{
name: "Location research",
_cid: "579b150756ea2dba79c1eff3",
_id: "579b150756ea2dba79c1f09e"
},
{
name: "Competition Analysis",
_cid: "579b150756ea2dba79c1eff3",
_id: "579b150756ea2dba79c1f077"
}
],
_cid: "579b150756ea2dba79c1efcb",
_id: "579b150756ea2dba79c1f0af"
},
Try something like this:
projects.items.map(i => ({
...i,
skills: i.skills.map(s => skills.items.find(skill => skill._id === s)),
solutions: i.solutions.map(s => solutions.items.find(solution => solution._id === s))
}));
I have a complex JavaScript object given below.
An example object:
var object= {
"name": "tfifkhul",
"id": "262761",
"children": [
{
"name": "rthrth",
"id": 0,
"children": [
{
"name": "test",
"id": "262762",
"children": []
}
]
},
{
"name": "rthsrth",
"id": 0,
"children": [
{
"name": "test",
"id": "262762",
"children": []
}
]
},
{
"name": "rthrthhrth",
"id": 0,
"children": [
{
"name": "test",
"id": "262762",
"children": [
{
"name": "rtjrtj",
"id": 0,
"children": [
{
"name": "fwefwefwef",
"id": "262768",
"children": []
}
]
},
{
"name": "hsrtjrtdjrtj",
"id": 0,
"children": [
{
"name": "we4yhesrhy",
"id": "262764",
"children": []
}
]
},
{
"name": "lol",
"id": "262763",
"children": [
{
"name": "fwefwefwef",
"id": "262768",
"children": [
{
"name": "87ok78",
"id": "262765",
"children": [
{
"name": "78o78",
"id": 0,
"children": [
{
"name": "we4yhesrhy",
"id": "262764",
"children": [
{
"name": "test1",
"id": 0,
"children": [
{
"name": "",
"id": "262766",
"children": []
}
]
},
{
"name": "test2",
"id": 0,
"children": [
{
"name": "",
"id": "262766",
"children": []
}
]
}
]
}
]
},
{
"name": "7o78o76o8",
"id": 0,
"children": [
{
"name": "",
"id": "262766",
"children": []
}
]
},
{
"name": "ko",
"id": 0,
"children": [
{
"name": "",
"id": "262767",
"children": []
}
]
}
]
}
]
}
]
}
]
}
]
}
]
};
I need to create a function to search for all matching values for key "id" with given value.
So far I have created one recursive function:
function searchOccurances(theObject, value,path) {
var result = null;
if(theObject instanceof Array) {
for(var i = 0; i < theObject.length; i++) {
result = searchOccurances(theObject[i],value,path+","+i);
}
}
else
{
for(prop in theObject) {
if(prop == 'id') {
if(theObject[prop] == value) {
keyOccurances.push(path);
}
}
if((theObject[prop] instanceof Array) || (theObject[prop] instanceof Object))
{
if((theObject[prop].length!=undefined)&&(theObject[prop].length!=0))
{
result = searchOccurances(theObject[prop],value,path+","+prop);
}
}
}
}
return result;
}
keyOccurances=[];
searchOccurances(object,262762,'');
console.log(keyOccurances);
//Output
[",children,0,children,0", ",children,1,children,0", ",children,2,children,0"] -- correct
keyOccurances=[];
searchOccurances(object,262768,'');
console.log(keyOccurances);
//Output
[",children,1,children,0,children,1,children,0", ",children,1,children,0,children,2,children,0"] --wrong
The function returns array of comma separated paths of matched value but doesn't seems to be getting right results. For the first call with value '262762' gives corrects path list but for value '262768' gives incorrect path list.
Kindly help.
I'd suggest to provide a better test object. Would you really have so many children with 'id = 0' in a real use case? Would you have 2 children with the same ID at all? That makes things pretty hard to debug.
Below is an example function that should work as expected.
function search(object, value) {
var res = [], searchPath;
(searchPath = function(children, path) {
var n, newPath;
for(n in children) {
if(typeof children[n].id !== 'undefined' && parseInt(children[n].id, 10) === value) {
res.push(path);
}
newPath = path.slice();
newPath.push(children[n].id);
searchPath(children[n].children, newPath);
}
})([ object ], []);
return res;
}
console.log(search(object, 262762));
console.log(search(object, 262768));
Output:
[["262761", 0], ["262761", 0], ["262761", 0]]
[["262761", 0, "262762", 0], ["262761", 0, "262762", "262763"]]
The above code is not (yet) bullet-proof but hopefully is it short enough to be easily understandable.
If I understand your questions correctly, you're looking for all paths where a specific id is present. I'd recommend not reinventing the wheel here and using an existing library. We use object-scan for most of our data processing now. It's powerful once you wrap your head around it. Here is how you'd answer your question
// const objectScan = require('object-scan');
const findKeys = (haystack, id) => objectScan(['**'], {
joined: true,
filterFn: ({ value }) => value.id === id
})(haystack);
const object = { name: 'tfifkhul', id: '262761', children: [{ name: 'rthrth', id: 0, children: [{ name: 'test', id: '262762', children: [] }] }, { name: 'rthsrth', id: 0, children: [{ name: 'test', id: '262762', children: [] }] }, { name: 'rthrthhrth', id: 0, children: [{ name: 'test', id: '262762', children: [{ name: 'rtjrtj', id: 0, children: [{ name: 'fwefwefwef', id: '262768', children: [] }] }, { name: 'hsrtjrtdjrtj', id: 0, children: [{ name: 'we4yhesrhy', id: '262764', children: [] }] }, { name: 'lol', id: '262763', children: [{ name: 'fwefwefwef', id: '262768', children: [{ name: '87ok78', id: '262765', children: [{ name: '78o78', id: 0, children: [{ name: 'we4yhesrhy', id: '262764', children: [{ name: 'test1', id: 0, children: [{ name: '', id: '262766', children: [] }] }, { name: 'test2', id: 0, children: [{ name: '', id: '262766', children: [] }] }] }] }, { name: '7o78o76o8', id: 0, children: [{ name: '', id: '262766', children: [] }] }, { name: 'ko', id: 0, children: [{ name: '', id: '262767', children: [] }] }] }] }] }] }] }] };
console.log(findKeys(object, '262762'));
/* =>
[ 'children[2].children[0]',
'children[1].children[0]',
'children[0].children[0]' ]
*/
console.log(findKeys(object, '262768'));
/* =>
[ 'children[2].children[0].children[2].children[0]',
'children[2].children[0].children[0].children[0]' ]
*/
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.8.0"></script>
Disclaimer: I'm the author of object-scan
Edit: The accepted answer didn't make much sense to me (based on the question), but here is how you could generate the same output
// const objectScan = require('object-scan');
const findIdPath = (haystack, id) => objectScan(['**'], {
reverse: false,
filterFn: ({ value, parents, context }) => {
if (value.id === id) {
context.push(parents.filter((p) => 'id' in p).map((p) => p.id).reverse());
}
}
})(haystack, []);
const object = { name: 'tfifkhul', id: '262761', children: [{ name: 'rthrth', id: 0, children: [{ name: 'test', id: '262762', children: [] }] }, { name: 'rthsrth', id: 0, children: [{ name: 'test', id: '262762', children: [] }] }, { name: 'rthrthhrth', id: 0, children: [{ name: 'test', id: '262762', children: [{ name: 'rtjrtj', id: 0, children: [{ name: 'fwefwefwef', id: '262768', children: [] }] }, { name: 'hsrtjrtdjrtj', id: 0, children: [{ name: 'we4yhesrhy', id: '262764', children: [] }] }, { name: 'lol', id: '262763', children: [{ name: 'fwefwefwef', id: '262768', children: [{ name: '87ok78', id: '262765', children: [{ name: '78o78', id: 0, children: [{ name: 'we4yhesrhy', id: '262764', children: [{ name: 'test1', id: 0, children: [{ name: '', id: '262766', children: [] }] }, { name: 'test2', id: 0, children: [{ name: '', id: '262766', children: [] }] }] }] }, { name: '7o78o76o8', id: 0, children: [{ name: '', id: '262766', children: [] }] }, { name: 'ko', id: 0, children: [{ name: '', id: '262767', children: [] }] }] }] }] }] }] }] };
console.log(findIdPath(object, '262762'));
// => [ [ '262761', 0 ], [ '262761', 0 ], [ '262761', 0 ] ]
console.log(findIdPath(object, '262768'));
// => [ [ '262761', 0, '262762', 0 ], [ '262761', 0, '262762', '262763' ] ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.8.0"></script>
Disclaimer: I'm the author of object-scan