I have an object with this structure (imagine it could be way bigger than this)
And I need to insert a new item inside, say, 'Name 3' children array. How would I go about creating a unique id for it? I have thought about saving the ids inside the object in a separate array and then creating one that is not on that, but I'd have to maintain it and I'm not sure that would be the best approach?
let obj = {
id: 1,
name: 'Name 1',
parent_id: null,
children: [{
id: 2,
name: 'Name 2',
parent_id: 1,
children: []
},
{
id: 3,
name: 'Name 3',
parent_id: 1,
children: [{
id: 4,
name: 'Name 4',
parent_id: 3,
children: []
}]
}
]
};
EDIT: The need for a unique id is for me to be able to delete an item. This is the code I've been given to work with, I can't alter the structure.
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 a html select element with options(categories). Upon selecting an option(category) I get the option's value and store it in a variable.
const currentSelectValue = $('option:selected', this).attr('value');
I also have a JSON array with all subcategories.
const myObjArr = {
data: [
{ id: 1, name: 'name_1', parent_id: '1' },
{ id: 2, name: 'name_2', parent_id: '2' },
{ id: 1, name: 'name_2', parent_id: '3' }
]
};
My goal is to get the selected option value and match it to the list of subcategories, find the parent_id(which is the value from the selected option) and list all the results.
I'm new to JavaScript, so a detailed answer with an example would be much, much appreciated. Thanks in advance!
Check this out JS .filter()
Assume you have 3 in your parent_id. Here is one line clean code solution
const myObjArr = {
data: [{
id: 1,
name: 'name_1',
parent_id: '1'
},
{
id: 2,
name: 'name_2',
parent_id: '2'
},
{
id: 1,
name: 'name_2',
parent_id: '3'
}
]
};
// if parent id is 3
const currentSelectValue = 3
const selected = myObjArr.data.filter((ele,index) => ele.parent_id == currentSelectValue
)
console.log(selected)
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
I have a list of products as an array of object, something like
[ {
id: 1,
price: 10,
name: 'product',
categories: [
{id: 1, name: 'category 1'} ]
},
{
id: 2,
price: 10,
name: 'product3',
categories: [
{id: 1, name: 'category 1'},
{id: 2, name: 'category 2'},]
},
...
]
And so on.
I'm trying to filter the product based on the category id, which is the best (and most modern) approach?, also since I'm working with Node.js, can it be better to work on a "copy" of the data, so that I always keep the full dataset intact for other uses? (like another filtering, or filter remove)
I'd use filter to apply a condition on each object. In that condition, I'd use some on the categories in order to find a product with at least one category that matches the condition:
const searchCategory = 1; // Just an exmaple
const result = products.filter(p => p.categories.some(c => c.id === searchCategory));
I would use .filter(), and in the callback, I'd use .some() to check if any of the categories have the correct id. If you only need one, you can use .find() instead of .filter().
Since you're working with object references, you have to be careful since the objects in the filtered array point to the same objects as the original array. In other words, if you modify the first element of the filtered array, the original array will update.
As for your question of whether you need to keep the full dataset, the way you phrased it is too broad to properly answer. You obviously should keep all the data somewhere, but at which level you use a filtered array and which level the full array is up to your architectural decisions.
Use Array.filter()
const arr = [ {
id: 1,
price: 10,
name: 'product',
categories: [
{id: 1, name: 'category 1'} ]
},
{
id: 2,
price: 10,
name: 'product3',
categories: [
{id: 1, name: 'category 1'},
{id: 2, name: 'category 2'},]
}
]
arr.filter(_o => _o.categories.filter(_c => _c.id === 2).length) // Change the "2" to whatereve you like to match the category ID
How to set the item in Angular JS Listbox. This should be shown as selected in Listbox.
HTML
<select multiple ="multiple" style="width:180px" ng-model="md_fruitpref" ng-options="fruit.Id as fruit.Name for fruit in Fruits"></select>
Controller
//Controller to set the items in Fruit
$scope.Fruits = [{
Id: 1,
Name: 'Apple'
}, {
Id: 2,
Name: 'Mango'
}, {
Id: 3,
Name: 'Orange'
}, {
Id: 4,
Name: 'Guava'
}, {
Id: 5,
Name: 'Banana'
}, {
Id: 6,
Name: 'Watermellon'
}];
This will fill the Listbox with the various fruits.
Now I want to show the webpage with all the fruits in the Listbox but selected with Apple and Watermellon. So I do this but it does not help.
$scope.md_fruitpref= [{
Id: 1,
Name: 'Apple',
Id: 6,
Name: 'Watermellon'
}];
How to set value in Angular JS Listbox?
Try:
// array with 2 elements (each one an object with the same properties)
$scope.md_fruitpref= [{
Id: 1,
Name: 'Apple'
}, {
Id: 6,
Name: 'Watermellon'
}];
The structure you currently have does not work because you only have one element in your md_fruitpref array, and the object is invalid because it uses the same keys twice.
Finally I found the answer to this.
It will be :-
$scope.md_fruitpref= [1,6];
After this line soon you will see the selection in Listbox