This question already has answers here:
How to map more than one property from an array of objects [duplicate]
(7 answers)
Closed last year.
I need to find first child element in array and just return it.
Here is problem because here is few children elements and i need loop thought each and return every first children element.
Example of array:
let allItems =
[{ id: 1 ,
name: 'Test 1' ,
children: [
id: 12,
title: 'Child element'
]
},
{
id: 2 ,
name: 'Test 2'
},
{
id: 3 ,
name: 'Test 3',
children: [
id: 12,
title: 'Child element',
children: [
id: 123,
title: 'GRAND Child element',
]
]
}]
What's the problem here? Since there can be many children elements, do I need to find a parent for each of those elements?
After looping i need array to be:
[{ id: 1 ,
name: 'Test 1'
},
{
id: 2 ,
name: 'Test 2'
},
{
id: 3 ,
name: 'Test 3'
}]
Wihout children elements.
What I am try:
allItems.map(item => item).filter(filteredItem => !filteredItem.children);
But this is no return me good results
Based on your expected output, here is my solution.
Also note, that you had missing curly braces with your children.
See you modified snippet below:
let allItems = [{
id: 1,
name: 'Test 1',
children: [{
id: 12,
title: 'Child element'
}]
},
{
id: 2,
name: 'Test 2'
},
{
id: 3,
name: 'Test 3',
children: [{
id: 12,
title: 'Child element',
children: [{
id: 123,
title: 'GRAND Child element',
}]
}]
}
]
console.log(allItems.map(item => {
return {
id: item.id,
name: item.name
}
}))
Using map and destructuring is a nice way to achieve what you're looking for
let allItems = [{
id: 1,
name: 'Test 1',
children: [{
id: 12,
title: 'Child element'
}]
},
{
id: 2,
name: 'Test 2'
},
{
id: 3,
name: 'Test 3',
children: [{
id: 12,
title: 'Child element',
children: [{
id: 123,
title: 'GRAND Child element',
}]
}]
}
];
const res = allItems.map(x => {
const {id, name} = x;
return {id, name};
});
console.log(res);
Use these propertys for call first child:
.firstchild==>this property calls first Node
.firstElementChild==>calls first element
Related
Data looks as follows:
Each node has a unique id (
Nodes have a children key which is either null or an array of ids.
Nodes can have one parent
Nodes do not have a parent or depth reference
Input:
const items = [
{
id: 1,
name: 'Item 1',
children: [ 2, 3 ]
},
{
id: 2,
name: 'Item 2',
children: null
},
{
id: 3,
name: 'Item 3',
children: null
},
{
id: 4,
name: 'Item 4',
children: [ 5 ]
},
{
id: 5,
name: 'Item 5',
children: [ 6 ]
},
{
id: 6,
name: 'Item 6',
children: null
},
}
]
Expected Output:
const tree = [
{
id: 1,
name: 'Item 1',
children: [
{
id: 2,
name: 'Item 2',
children: null
},
{
id: 3,
name: 'Item 3',
children: null
},
]
},
{
id: 4,
name: 'Item 4',
children: [
{
id: 5,
name: 'Item 5',
children: [
{
id: 6,
name: 'Item 6',
children: null
}
]
}
]
}
]
If this is in fact possible, would love to 1) see how it is done and 2) see if there are any libraries that handle this use case.
The resulting structure is more a forest than a tree, as not all nodes are connected and you have multiple "roots".
You can first key the nodes by their id in a Map, and then iterate all children arrays to replace their contents by the corresponding items found in the Map. At the same time keep track of all the children, so that at the end you can identify which items are not children, and therefore belong in the result array:
const items = [{id: 1,name: 'Item 1',children: [ 2, 3 ]},{id: 2,name: 'Item 2',children: null},{id: 3,name: 'Item 3',children: null},{id: 4,name: 'Item 4',children: [ 5 ]},{id: 5,name: 'Item 5',children: [ 6 ]},{id: 6,name: 'Item 6',children: null},];
const map = new Map(items.map(item => [item.id, item]));
const children = new Set;
for (const item of items) {
if (!item.children) continue;
for (const id of item.children) children.add(id);
item.children = item.children?.map(id => map.get(id));
}
const forest = items.filter(({id}) => !children.has(id));
console.log(forest);
I have been looking around for a JavaScript method to return the index of a value but I can't seem to find one that works.
I have the following code:
let topics = [
{
id: 1,
name: 'Topic 1',
children: [
{
id: 2,
name: 'Subtopic 1.1' <---- Searching for this value
}
]
}
];
Is there a method to use on the topics variable to search through the entire object array at once for the value of Subtopic 1.1 and then return the parent index, which in this case would be 0.
There isn't a single function, but you can nest an Array.prototype.find function inside an Array.prototype.findIndex without issue to achieve what you want (findIndex to search through the parents, find to search through the children):
let topics = [{
id: 1,
name: 'Topic 1',
children: [{
id: 2,
name: 'Subtopic 1.1' // <---- Searching for this value
}]
},
{
id: 2,
name: 'Topic 6',
children: [{
id: 5,
name: 'Subtopic 1.7'
}]
},
{
id: 3,
name: 'Topic 9',
children: [{
id: 4,
name: 'Subtopic 1.192'
},
{
id: 28,
name: 'Subtopic 999'
}],
},
];
function findParentIndex(name) {
return topics.findIndex(topic => topic.children.find(child => child.name === name));
}
console.log(findParentId("Subtopic 1.192")); // 3
console.log(findParentId("Subtopic 1.1")); // 1
console.log(findParentId("Not in the list")); // -1
You can use array.findIndex()
let topics = [{
id: 1,
name: 'Topic 1',
children: [{
id: 1,name: 'Subtopic 1.2'
}, {
id: 4,name: 'Subtopic 1.4'
}, {
id: 2, name: 'Subtopic 1.1'
}]
}];
const findIndexOf = val => {
return topics[0].children.findIndex(e => e.name.trim() === val.trim())
}
console.log(findIndexOf('Subtopic 1.1'))
No.
You would iterate through children, then have a nested loop iterating through each index value. If you find a match, the incrementing variable from the parent loop is the index you want.
edit: code example
let topics = [
{
id: 1,
name: 'Topic 1',
children: [
{
id: 2,
name: 'Subtopic 1.1'
},
{
id: 2,
name: 'Subtopic 3.1'
},
{
id: 2,
name: 'Subtopic 1.1'
},
{
id: 2,
name: 'Subtopic 2.1'
},
{
id: 2,
name: 'Subtopic 1.1'
}
]
}
];
for (let i in topics[0]["children"]) {
if (topics[0]["children"][i]["name"] == "Subtopic 1.1") {
console.log(i)
}
}
The Below code, not returning a flat array, is highly confusing, Need a flat array of deeply nested array of objects
have attached jsfiddle link https://jsfiddle.net/k6swuvox/
const arr = [{
id: 1,
name: 'XYZ 1'
}, {
id: 2,
name: 'XYZ 2',
children: [{
id: 5,
name: 'XYZ 5'
}, {
id: 6,
name: 'XYZ 6',
age: 29,
children: [{
id: 7,
name: 'XYZ 7'
}, {
id: 8,
name: 'XYZ 8'
}]
}]
}, {
id: 3,
name: 'XYZ 3'
}, {
id: 4,
name: 'XYZ 4'
}]
const flats = data => data.map(e => {
if (e.children) {
return [...flats(e.children), e]
} else {
console.log("E", e);
return e
}
})
console.log(flats(arr));
With your current code, you will sometimes return an array from the callback:
return [...flats(e.children),e]
and you'll sometimes return a plain object:
else {console.log("E",e);return e }
so the result will be a mix of arrays and plain objects, instead of an array of only objects.
Use flatMap instead, which will implement the flattening you're looking for for you. You'll also need to remove the .children property from items with children before returning them.
const arr=[{id:1,name:"XYZ 1"},{id:2,name:"XYZ 2",children:[{id:5,name:"XYZ 5"},{id:6,name:"XYZ 6",age:29,children:[{id:7,name:"XYZ 7"},{id:8,name:"XYZ 8"}]}]},{id:3,name:"XYZ 3"},{id:4,name:"XYZ 4"}];
const flats = data => data.flatMap(e=>{
const { children, ...objWithoutChildren } = e;
return children
? [...flats(children), objWithoutChildren]
: e;
});
console.log(flats(arr));
Here is an iterative solution using object-scan
// const objectScan = require('object-scan');
const arr = [{ id: 1, name: 'XYZ 1' }, { id: 2, name: 'XYZ 2', children: [{ id: 5, name: 'XYZ 5' }, { id: 6, name: 'XYZ 6', age: 29, children: [{ id: 7, name: 'XYZ 7' }, { id: 8, name: 'XYZ 8' }] }] }, { id: 3, name: 'XYZ 3' }, { id: 4, name: 'XYZ 4' }];
const flatten = objectScan(['**(^children$).id'], {
useArraySelector: false,
rtn: 'parent',
reverse: false,
afterFn: (state) => {
state.result = state.result.map(({ id, name }) => ({ id, name }));
}
});
console.log(flatten(arr));
// => [ { id: 1, name: 'XYZ 1' }, { id: 2, name: 'XYZ 2' }, { id: 5, name: 'XYZ 5' }, { id: 6, name: 'XYZ 6' }, { id: 7, name: 'XYZ 7' }, { id: 8, name: 'XYZ 8' }, { id: 3, name: 'XYZ 3' }, { id: 4, name: 'XYZ 4' } ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#15.0.0"></script>
Disclaimer: I'm the author of object-scan
Need a flat array of deeply nested array of objects
In that case, I'd prefer recursive to get the flexible and high deep level array.
const arr = [{id:1,name:'XYZ 1'},{id:2,name:'XYZ 2',children:[{id:5,name:'XYZ 5'},{id:6,name:'XYZ 6',age:29,children:[{id:7,name:'XYZ 7'},{id:8,name:'XYZ 8'}]}]},{id:3,name:'XYZ 3'},{id:4,name:'XYZ 4'}];
const recursive = (array) => array.reduce((acc, {children = [], ...others}) => {
acc.push(others);
if(children.length > 0) // Base recurisve here.
acc = acc.concat(recursive(children));
return acc;
}, []);
console.log(recursive(arr));
==> As a result, the content structure will make sure like this
I have the following data structure
menu: [ { id: 1, title: 'Test 1', children: [] },
{ id: 2, title: 'Test 2', children: [
{ id: 5, title: 'Test 5', children: [] },
{ id: 6, title: 'Test 6', children: [] },
{ id: 7, title: 'Test 7', children: [] },
{ id: 8, title: 'Test 8', children: [] },
] },
{ id: 3, title: 'Test 3', children: [
{ id: 9, title: 'Test 9', children: [] },
{ id: 10, title: 'Test 10', children: [] },
{ id: 11, title: 'Test 11', children: [] },
{ id: 12, title: 'Test 12', children: [] },
] },
{ id: 4, title: 'Test 4', children: [] },
]
How can remove object with Title 'Test 5'? Or from sub array in children arr?
onDeleteClick(item) {
const menuCopy = JSON.parse(JSON.stringify(this.menu));
const index = menuCopy.indexOf(item);
if (index !== -1) {
menuCopy.splice(index, 1);
} else {
menuCopy.map((el) => {
if (el.children.length) {
el.children.map((child) => {
if (child.Id === item.Id) {
console.log(child);
}
});
}
});
}
this.setMenu(menuCopy);
}
I am stuck at this point. I think that here should be used recursion but i have no idea how to implement this.
const menu = [ { id: 1, title: 'Test 1', children: [] },
{ id: 2, title: 'Test 2', children: [
{ id: 5, title: 'Test 5', children: [] },
{ id: 6, title: 'Test 6', children: [
{ id: 5, title: 'Test 5', children: [] },
{ id: 7, title: 'Test 7', children: [] },
{ id: 8, title: 'Test 8', children: [] }
] },
{ id: 7, title: 'Test 7', children: [] },
{ id: 8, title: 'Test 8', children: [] },
] },
{ id: 3, title: 'Test 3', children: [
{ id: 9, title: 'Test 9', children: [] },
{ id: 10, title: 'Test 10', children: [] },
{ id: 11, title: 'Test 11', children: [] },
{ id: 12, title: 'Test 12', children: [] },
] },
{ id: 4, title: 'Test 4', children: [] },
];
const excludeChildrenFromTitle = (arr, excludedChildTitle) => {
return arr.map((item) => {
const children = excludeChildrenFromTitle(item.children.filter((child) => child.title !== excludedChildTitle), excludedChildTitle);
return {
...item,
children
}
});
};
console.log(excludeChildrenFromTitle(menu, 'Test 5'))
Using a simple map for the whole menu array and then filtering every children array from each menu item can do the job.
I have updated the answer to remove the excluded child from sub array too.
You can filter first each first-level element and then second-level with map:
var l = [{ id: 1, title: 'Test 1', children: [] }, { id: 2, title: 'Test 2', children: [ { id: 5, title: 'Test 5', children: [] }, { id: 6, title: 'Test 6', children: [] }, { id: 7, title: 'Test 7', children: [] }, { id: 8, title: 'Test 8', children: [] }, ] }, { id: 3, title: 'Test 3', children: [ { id: 9, title: 'Test 9', children: [] }, { id: 10, title: 'Test 10', children: [] }, { id: 11, title: 'Test 11', children: [] }, { id: 12, title: 'Test 12', children: [] }, ] }, { id: 4, title: 'Test 4', children: [] },
{ id: 5, title: 'Test 5', children: [] }, ];
const removeTitleByValue = (arr, titleValue) => {
return arr
.filter(e => e.title !== titleValue)
.map((e2) => {
const children = e2.children.filter((ch) => ch.title !== titleValue);
return { ...e2, children }
});
};
console.log(removeTitleByValue(l, 'Test 5'))
I have an array like that:
[{
id: 1,
name: 'Proposal'
},
{
id: 2,
name: 'Contract',
children: [
{
name: 'Approval',
component: '/approval'
},
{
name: 'Cancellation',
component: '/cancellation'
}
]
}]
and another like that:
[{
id: 1,
name: 'Proposal'
},
{
id: 2,
name: 'Contract',
children: [
{
name: 'Approval',
component: '/approval'
}
]
},
{
id: 3,
name: 'Example'
}]
My question is how is the best way to filter arrays, and remove one if have duplicated or more, even in array of children. Or the best, is like arrays merge!