Fix: JS recursive function to get the nested (multilevel) child objects as array of objects
const myObj = { parent1: { child1: { lastChild1: { test: 'cool'} }, child2: { lastChild2: { test: 'cool'} } }, parent2: { child2_1: { lastChild2_1: { test: 'cool'} }, child2_2: { lastChild2_2: { test: 'cool'} } } }
function getOptions(obj) { return Object.keys(obj).reduce((acc, cur) => { acc.push({ id: cur, label: cur, children: recurseList(obj[cur]) }) return acc; }, [])} function recurseList(obj) { return Object.keys(obj).reduce((acc, cur) => { if(obj[cur] instanceof Object) { let data = { id: cur, label:cur } const children = recurseList(obj[cur]); If(children.length) { data.children = children } acc.push(data) } return acc; }, [])}
var result = getOptions(myObj)console.log('result', result)
Search nested array of objects and return full parents as results in JavaScript
You could take a recursive approach and check if the nested arrays have the wanted name.
function searchPages(array, string) { const find = ({ name, pages }) => name.includes(string) || pages && pages.some(find); return array.filter(find);}
const data = [{ name: '1', pages: [{ name: '1.1', pages: [] }, { name: '1.2', pages: [] }] }, { name: '2', pages: [] }, { name: '3', pages: [] }], searchResults = searchPages(data, '1.1');
console.log(searchResults);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Recursively searching a nested array in JS
There's an error in your code, at the moment you're just recursing on a single branch of the three, you're not recursing across the whole data structure, infact if you're trying to search for "node_modules" your code returns undefined.
Try to apply this tiny modification to your code
const data = [ { "type": "directory", "name": "/home/user/test-tree", "contents": [ { "type": "directory", "name": "my-folder", "contents": [ { "type": "directory", "name": "nested-folder", "contents": [] } ] }, { "type": "directory", "name": "node_modules", "contents": [ { "type": "directory", "name": "gunzip-file", "contents": [] } ] } ] }];
function treeSearch(array, dirName) { for (let i = 0; i < array.length; i++) { if (array[i].name === dirName) { return array[i]; } else if (array[i].contents && array[i].contents.length) { const result = treeSearch(array[i].contents, dirName); // return the result only if it's actually found otherwise keep looping if(result) return result; } }}
console.log(treeSearch(data, "node_modules"));
Recursively filter array of objects
Using .filter()
and making a recursive call as I described in the comment above is basically what you need. You just need to update each .children
property with the result of the recursive call before returning.
The return value is just the .length
of the resulting .children
collection, so if there's at least one, the object is kept.
var res = input.filter(function f(o) {
if (o.value.includes("Hit")) return true
if (o.children) {
return (o.children = o.children.filter(f)).length
}
})
const input = [ { value: 'Miss1', children: [ { value: 'Miss2' }, { value: 'Hit1', children: [ { value: 'Miss3' } ] } ] }, { value: 'Miss4', children: [ { value: 'Miss5' }, { value: 'Miss6', children: [ { value: 'Hit2' } ] } ] }, { value: 'Miss7', children: [ { value: 'Miss8' }, { value: 'Miss9', children: [ { value: 'Miss10' } ] } ] }, { value: 'Hit3', children: [ { value: 'Miss11' }, { value: 'Miss12', children: [ { value: 'Miss13' } ] } ] }, { value: 'Miss14', children: [ { value: 'Hit4' }, { value: 'Miss15', children: [ { value: 'Miss16' } ] } ] },];
var res = input.filter(function f(o) { if (o.value.includes("Hit")) return true
if (o.children) { return (o.children = o.children.filter(f)).length }})console.log(JSON.stringify(res, null, 2))
Javascript - Convert Nested Object to Array of items
You could take an iterative and recursive approach by checking header keeping the corresponding divider and iterate children.
Then you need to add the standard object for any item.
The recursive callback uses a closure over the group. if not set, the group is a root item.
function getParts(array) { var result = []; array.forEach(function iter(group) { return function ({ id, name, children }, i, { length }) { if (!group && children.length) { result.push({ header: name }); } if (group || !children.length) { result.push({ name, group: group || name, id }); } children.forEach(iter(name)); if (!group && i + 1 !== length) { result.push({ divider: true }); } }; }('')); return result;}
var data = [{ id: 1, name: "Electronics", path: "Electronics", children: [{ id: 2, name: "Laptops & PC", path: "Electronics > Laptops & PC", children: [] }, { id: 7, name: "Phones & Accessories", path: "Electronics > Phones & Accessories", children: [{ id: 8, name: "Smartphones", path: "Electronics > Phones & Accessories > Smartphones", children: [{ id: 9, name: "Android", path: "Electronics > Phones & Accessories > Smartphones > Android", children: [] }, { id: 10, name: "iOS", path: "Electronics > Phones & Accessories > Smartphones > iOS", children: [] }] }] }] }, { id: 11, name: "Software", path: "Software", children: [] }, { id: 11, name: "Software", path: "Software", children: [] }, { id: 11, name: "Software", path: "Software", children: [] }], result = getParts(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Flatten a deeply nested data structure of arrays, objects + strings into a list of data items while mapping the former parent-child relationship too
First of all, I would not be answering if there was not already a good answer. Please, on StackOverflow, always show your own attempts and explain where you got stuck. But since there is already an answer, I think this version might be a bit simpler.
Second, I'm assuming this output format is some sort of directed graph, that the first half is your list of vertices and the second half a list of edges. If so I don't know if your output format is constrained here. But if you had the option, I would think a better structure would be an object with vertices
and edges
properties, each containing an array. You might then not need the edges' ids. And the code could also be simplified.
This version first converts to an intermediate structure like this:
[
{id: "1", data: {label: {author: "John Doe", age: 26}}, children: [
{id: "2", data: {label: "books"}, children: [
{id: "3", data: {label: {title: "Book 1"}}, children: []},
{id: "4", data: {label: {title: "Book 2"}}, children: [
{id: "5", data: {label: "chapters"}, children: [
{id: "6", data: {label: {title: "No Way Home"}}, children: []}
]}
]}
]}
]}
]
Then we flatten that structure into the first section of the output and use it to calculate the relationships (edges?) between nested nodes to go in the second section.
The code looks like this:
const transform = (input) => {
const extract = (os, nextId = ((id) => () => String (++ id)) (0)) => os .map ((o) => ({
id: nextId(),
data: {label: Object .fromEntries (Object .entries (o) .filter (([k, v]) => !Array .isArray (v)))},
children: Object .entries (o) .filter (([k, v]) => Array .isArray (v)) .flatMap (([k, v]) => [
{id: nextId(), data: {label: k}, children: extract (v, nextId)},
])
}))
const relationships = (xs) =>
xs .flatMap (({id: target, children = []}) => [
... children .map (({id: source}) => ({id: `e${source}-${target}`, source, target})),
... relationships (children),
])
const flatten = (xs) =>
xs .flatMap (({children, ...rest}) => [rest, ... flatten (children)])
const res = extract (input)
return [...flatten (res), ... relationships (res)]
}
const input = [{author: "John Doe", age : 26, books: [{title: "Book 1"}, {title: "Book 2", chapters: [{title: "No Way Home", page: 256}]}]}]
console .log (transform (input))
.as-console-wrapper {max-height: 100% !important; top: 0}
javascript find child object in nested arrays
Caveat: This uses a couple of Array.prototype
functions that were only added in ECMAScript 5 and thus will not work with older browsers unless you polyfill them.
You can loop over all first-level objects in your array, and then filter the categories based on your condition and collect all matches in an array. Your final result will be the first element in the array of matches (no match found if array is empty).
var matches = [];
var needle = 100; // what to look for
arr.forEach(function(e) {
matches = matches.concat(e.Categories.filter(function(c) {
return (c.Id === needle);
}));
});
console.log(matches[0] || "Not found");
JSFiddle: http://jsfiddle.net/b7ktf/1/
References:
Array.prototype.forEach
Array.prototype.concat
Array.prototype.filter
JS Recursive Nested JSON Array Children Join Key
You can use a a recursive approach, say, creating a function getPaths
that will get a list of paths using a property
key as an input.
In this case we'll use 'NAME', and build up an array of the relevant paths.
let input = [ { "PRODUCT_CATEGORY_ID": "1", "NAME": "OTOMOBİL PARÇALARI", "DESCRIPTION": "Araba Parçaları", "ACTIVE": "True", "PARENT_PRODUCT_CATEGORY_ID": "", "children": [ { "PRODUCT_CATEGORY_ID": "3", "NAME": "HONDA PARÇALARI", "DESCRIPTION": "Honda Parçaları", "ACTIVE": "True", "PARENT_PRODUCT_CATEGORY_ID": "1" }, { "PRODUCT_CATEGORY_ID": "4", "NAME": "RENAULT PARÇALARI", "DESCRIPTION": "Renault Parçaları", "ACTIVE": "True", "PARENT_PRODUCT_CATEGORY_ID": "1", "children": [ { "PRODUCT_CATEGORY_ID": "5", "NAME": "MINIMAL RENAULT PARÇALARI", "DESCRIPTION": "", "ACTIVE": "True", "PARENT_PRODUCT_CATEGORY_ID": "4" } ] } ] } ]
function getPaths(obj, property, path = '') {
const paths = [];
for(let k in obj) {
if (typeof(obj[k]) === 'object') {
paths.push(...getPaths(obj[k], property, path));
} else if (k === property) {
path += (path ? ' > ' : '') + obj[k];
paths.push(path)
}
}
return paths;
}
console.log('Paths:', getPaths(input, 'NAME'))
Create nested JSX list items from multi-level nested array of objects reactjs
You can "render" your children into a variable and use this directly in your component.
The trick then is to use a recursive component. That way it doesn‘t matter how deep your tree is. You don‘t need to edit this component if your tree gets deeper.
Here is how that might look like:
function ListItem({ item }) {
let children = null;
if (item.values) {
children = (
<ul>
{item.values.map(i => <ListItem item={i} key={i.id} />)}
</ul>
);
}
return (
<li>
{item.name}
{children}
</li>
);
}
Here is a working example on Codesandbox with your data.
Related Topics
How to Add Spaces to for Loop Output in JavaScript
Vue.Js Refs Are Undefined, Even Though This.$Refs Shows Theyre There
How to Return Blank String If Object Is Undefined in Angularjs Forms
Javascript Check If Character Is a Vowel
React - Clearing an Input Value After Form Submit
Clicking a Button Within a Form Causes Page Refresh
Javascript: Get All Months Between Two Dates
Remove a Specific String from Url and Redirect
How to Send Secure Parameter in Ajax Request
Slick Slider - How to Keep the Active Pagination (Dot) Always Centered
How to Send a Http Delete Request from Browser
How to I Retrieve Last Part of Url and Use It in HTML
Calculate String Value in Javascript, Not Using Eval
Modify Classname When Element Is Clicked in React
How to Capture the Browser Window Close Event
Php - Return Confirm Within PHP Issue