How to keep from each parent only children by id from object - javascript

I am trying to keep only children from each parent if it matches a child's id from a given list of parent/child ids.
var parentIds = ['1','2','3'];
var childrenIds = ['2','3','5'];
Parent with id '1' should only have children with id '2', parent with id '2' should only have children with id '3' and parent with id '3' should only have children with id '5'. So, parent id matches children id in same position from both arrays.
Example of initial object:
var object = [
{
name: "parent1",
id: 1,
option_values: [
{
name: "child1",
id: 1
},
{
name: "child2",
id: 2
},
{
name: "child8",
id: 8
}
]
},
{
name: "parent2",
id: 2,
option_values: [
{
name: "child3",
id: 3
},
{
name: "child1",
id: 1
},
{
name: "child9",
id: 9
}
]
},
{
name: "parent3",
id: 3,
option_values: [
{
name: "child5",
id: 5
},
{
name: "child4",
id: 4
},
{
name: "child13",
id: 13
}
]
},
]
Expected result:
var result = [
{
name: "parent1",
id: 1,
option_values: [
{
name: "child2",
id: 2
}
]
},
{
name: "parent2",
id: 2,
option_values: [
{
name: "child3",
id: 3
}
]
},
{
name: "parent3",
id: 3,
option_values: [
{
name: "child5",
id: 5
}
]
},
]

Loop through the objects. Find the index of the parent ID in the parentIds array, then get the corresponding element of childIds. Then filter the option_values array using that child ID.
var object = [{
name: "parent1",
id: 1,
option_values: [{
name: "child1",
id: 1
},
{
name: "child2",
id: 2
},
{
name: "child8",
id: 8
}
]
},
{
name: "parent2",
id: 2,
option_values: [{
name: "child3",
id: 3
},
{
name: "child1",
id: 1
},
{
name: "child9",
id: 9
}
]
},
{
name: "parent3",
id: 3,
option_values: [{
name: "child5",
id: 5
},
{
name: "child4",
id: 4
},
{
name: "child13",
id: 13
}
]
},
];
var parentIds = ['1', '2', '3'];
var childrenIds = ['2', '3', '5'];
object.forEach(obj => {
let idIndex = parentIds.indexOf(String(obj.id));
if (idIndex != -1) {
let childId = parseInt(childrenIds[idIndex]);
obj.option_values = obj.option_values.filter(child => child.id == childId);
}
});
console.log(object);

Related

How to reduce an array and add a count as a new field?

I have an array of objects, however i need the array to add a count onto each object, and also remove any duplicates. Is there a simple way to achieve this?
CURRENT
[
{ id: 2, name: 'Adventure' },
{ id: 6, name: 'Crime' },
{ id: 2, name: 'Adventure' },
{ id: 3, name: 'Beautiful' },
{ id: 7, name: 'Drama' },
{ id: 2, name: 'Adventure' }
]
EXPECTED
[
{ id: 2, name: 'Adventure', count: 3 },
{ id: 6, name: 'Crime', count: 1 },
{ id: 3, name: 'Beautiful', count: 1 },
{ id: 7, name: 'Drama', count: 1 }
]
let current = [
{ id: 2, name: 'Adventure' },
{ id: 6, name: 'Crime' },
{ id: 2, name: 'Adventure' },
{ id: 3, name: 'Beautiful' },
{ id: 7, name: 'Drama' },
{ id: 2, name: 'Adventure' }
]
let expected = current.reduce((acc, cur) => {
let curFind = acc.find(item => item.id === cur.id)
if (curFind) {
curFind.count++
return acc
} else {
return [...acc, {
...cur,
count: 1
}]
}
}, [])
console.log('expected:', expected)

Processing an array of objects according to element nesting via Vanilla JS / JQuery

I have an array of objects that I have to process and then include data from it to HTML. The problem is that now everything is displayed one by one and if I try to toggle class to li element, it toggles to all li elements. The data can be changed dynamically so I cannot access elements by ID.
I want to access the "main" category first (desserts, water, tea), then be able to proceed to subcategory of the selected main category etc. Further I will create a menu like in the screenshot (a one menu, a pic shows different states of it)
I have 2 problems now:
For some reason the main category isn't showing at all - why is it happening?
How can I access the elements according to hierarchy and nesting?
const menu = [
{
id: 1,
name: "Desserts",
groups: [
{
id: 2,
name: "Cold",
groups: [
{
id: 3,
name: "Ice Cream",
groups: []
},
{
id: 4,
name: "Cold brew coffee",
groups: []
}
]
},
{
id: 5,
name: "Hot",
groups: [
{
id: 6,
name: "Pancakes",
groups: []
},
{
id: 7,
name: "Apple pie",
groups: []
}
]
}
]
},
{
id: 8,
name: "Water",
groups: []
},
{
id: 7,
name: "Tea",
groups: [
{
id: 8,
name: "Green tea",
groups: [
{
id: 9,
name: "With Jasmine",
groups: []
},
{
id: 10,
name: "Plain",
groups: []
}
]
},
{
id: 11,
name: "Black Tea",
groups: []
}
]
}
];
let menuEl = document.querySelector(".funding__categories");
addElements(menuEl, menu[0].groups);
function addElements(parent, arr) {
let allCategories = parent.appendChild(document.createElement("ul"));
allCategories.classList.add("parent");
arr.forEach((el) => {
let subCategory = allCategories.appendChild(document.createElement("li"));
subCategory.dataset.id = el.id;
subCategory.textContent = el.name;
if (el.groups.length > 0) addElements(subCategory, el.groups);
});
}
<div class="funding__categories"></div>
The first problem is because you're passing menu[0].groups to the function. That skips over the top-level categories and starts at the items nested under Desserts. Pass menu as the argument.
I don't understand the second question. Access them in what way?
const menu = [
{
id: 1,
name: "Desserts",
groups: [
{
id: 2,
name: "Cold",
groups: [
{
id: 3,
name: "Ice Cream",
groups: []
},
{
id: 4,
name: "Cold brew coffee",
groups: []
}
]
},
{
id: 5,
name: "Hot",
groups: [
{
id: 6,
name: "Pancakes",
groups: []
},
{
id: 7,
name: "Apple pie",
groups: []
}
]
}
]
},
{
id: 8,
name: "Water",
groups: []
},
{
id: 7,
name: "Tea",
groups: [
{
id: 8,
name: "Green tea",
groups: [
{
id: 9,
name: "With Jasmine",
groups: []
},
{
id: 10,
name: "Plain",
groups: []
}
]
},
{
id: 11,
name: "Black Tea",
groups: []
}
]
}
];
let menuEl = document.querySelector(".funding__categories");
addElements(menuEl, menu);
function addElements(parent, arr) {
let allCategories = parent.appendChild(document.createElement("ul"));
allCategories.classList.add("parent");
arr.forEach((el) => {
let subCategory = allCategories.appendChild(document.createElement("li"));
subCategory.dataset.id = el.id;
subCategory.textContent = el.name;
if (el.groups.length > 0) addElements(subCategory, el.groups);
});
}
<div class="funding__categories"></div>

How to get list of parents id in json object

My nested json array looks like:
[
{
id: 1,
name: "Mike",
children: [
{ id: 2, name: "MikeC1" },
{ id: 3, name: "MikeC2" },
{
id: 4, name: "MikeC3",
children: [{ id: 5, name: "MikeCC1" }]
},
]
},
{
id: 6,
name: "Json",
children: [
{ id: 7, name: "JsonC1" },
{ id: 8, name: "JsonC2" },
{
id: 9, name: "JsonC3",
children: [{ id: 10, name: "JsonCC1" },{ id: 11, name: "JsonCC2" }]
},
]
}
]
Now I get a id like "11"
then get the parent ids array in json like [6,9,11]
How to do?
var id = 11
console.log(findParent(id))
//result is [6,9,11]
You need to do recursive search
const persons = [
{
id: 1,
name: "Mike",
children: [
{ id: 2, name: "MikeC1" },
{ id: 3, name: "MikeC2" },
{
id: 4, name: "MikeC3",
children: [{ id: 5, name: "MikeCC1" }]
},
]
},
{
id: 6,
name: "Json",
children: [
{ id: 7, name: "JsonC1" },
{ id: 8, name: "JsonC2" },
{
id: 9, name: "JsonC3",
children: [{ id: 10, name: "JsonCC1" },{ id: 11, name: "JsonCC2" }]
},
]
}
];
function searchRecursive(items, id) {
const allIds = [];
items.forEach(item => {
if(item.id === id) {
allIds.push(item.id);
}
else if(item.children) {
const ids = searchRecursive(item.children, id);
if(ids.length) allIds.push(item.id);
ids.forEach(id => allIds.push(id));
}
});
return allIds;
}
console.log(searchRecursive(persons, 11));

Merge Duplicate object in array

I have an array I need to merge duplicate values with the sum of amount.
What would be an efficient algorithm
var arr = [{
item: {
id: 1,
name: "Abc"
},
amount: 1
}, {
item: {
id: 1,
name: "Abc"
},
amount: 2
}, {
item: {
id: 2,
name: "Abc"
},
amount: 2
},{
item: {
id: 1,
name: "Abc"
},
amount: 2
}]
I need solution as
[{
item: {
id: 1,
name: "Abc"
},
amount: 5
}, {
item: {
id: 2,
name: "Abc"
},
] amount: 2
}]
simply use Object.values() with Array.reudce() to merge objects and then get the values:
var arr = [{ item: { id: 1, name: "Abc" }, amount: 1 }, { item: { id: 1, name: "Abc" }, amount: 2 }, { item: { id: 2, name: "Abc" }, amount: 2 },{ item: { id: 1, name: "Abc" }, amount: 2 }];
var result = Object.values(arr.reduce((a,curr)=>{
if(!a[curr.item.id])
a[curr.item.id] = Object.assign({},curr); // Object.assign() is used so that the original element(object) is not mutated.
else
a[curr.item.id].amount += curr.amount;
return a;
},{}));
console.log(result);
used map to catch em all :D
var arr = [{ item: { id: 1, name: "Abc" }, amount: 1 }, { item: { id: 1, name: "Abc" }, amount: 2 }, { item: { id: 2, name: "Abc" }, amount: 2 },{ item: { id: 1, name: "Abc" }, amount: 2 }];
var res = {};
arr.map((e) => {
if(!res[e.item.id]) res[e.item.id] = Object.assign({},e); // clone, credits to: #amrender singh
else res[e.item.id].amount += e.amount;
});
console.log(Object.values(res));

How to unwind an Array of Objects in NodeJS?

I want to unwind an array of objects which have arrays of objects nested. The level of nesting is not defined and is not consistent throughout the array.
Here's my sample data
var data = [{
id: 1,
name: 'Harshal',
subjects: [{
id: 1,
name: 'English',
chapters: [{
id: 1,
name: 'Grammar'
}, {
id: 2,
name: 'Comprehension'
}]
}, {
id: 2,
name: 'Maths',
chapters: [{
id: 1,
name: 'Algebra'
}, {
id: 2,
name: 'Geometry'
}]
}]
}, {
id: 2,
name: 'Pankaj',
subjects: [{
id: 3,
name: 'Marathi',
chapters: [{
id: 1,
name: 'Kavita',
topics: [{
id: 1,
name: 'Topic 1'
}]
}]
}, {
id: 4,
name: 'Hindi',
chapters: [{
id: 1,
name: 'Katha',
topics: [{
id: 2,
name: 'Topic 2'
}, {
id: 3,
name: 'Topic 3'
}]
}]
}]
}];
I want to get an output like this:
var op = [{
id: 1,
name: 'Harshal',
subjects: {
id: 1,
name: 'English',
chapters: {
id: 1,
name: 'Grammar'
}
}
}, {
id: 1,
name: 'Harshal',
subjects: {
id: 1,
name: 'English',
chapters: {
id: 2,
name: 'Comprehension'
}
}
}, {
id: 1,
name: 'Harshal',
subjects: {
id: 2,
name: 'Maths',
chapters: {
id: 1,
name: 'Algebra'
}
}
}, {
id: 1,
name: 'Harshal',
subjects: {
id: 2,
name: 'Maths',
chapters: {
id: 2,
name: 'Geometry'
}
}
}, {
id: 2,
name: 'Pankaj',
subjects: {
id: 3,
name: 'Marathi',
chapters: {
id: 1,
name: 'Kavita',
topics: {
id: 1,
name: 'Topic 1'
}
}
}
}, {
id: 2,
name: 'Pankaj',
subjects: {
id: 4,
name: 'Hindi',
chapters: {
id: 1,
name: 'Katha',
topics: {
id: 2,
name: 'Topic 2'
}
}
}
}, {
id: 2,
name: 'Pankaj',
subjects: {
id: 4,
name: 'Hindi',
chapters: {
id: 1,
name: 'Katha',
topics: {
id: 3,
name: 'Topic 3'
}
}
}
}];
I have tried to work with pull-unwind but I guess there's some issues with it. If anyone has any other ideas, I'm open to implement those.
Have you tried recursion?
var data = [{
id: 1,
name: 'Harshal',
subjects: [{
id: 1,
name: 'English',
chapters: [{
id: 1,
name: 'Grammar'
}, {
id: 2,
name: 'Comprehension'
}]
}, {
id: 2,
name: 'Maths',
chapters: [{
id: 1,
name: 'Algebra'
}, {
id: 2,
name: 'Geometry'
}]
}]
}, {
id: 2,
name: 'Pankaj',
subjects: [{
id: 3,
name: 'Marathi',
chapters: [{
id: 1,
name: 'Kavita',
topics: [{
id: 1,
name: 'Topic 1'
}]
}]
}, {
id: 4,
name: 'Hindi',
chapters: [{
id: 1,
name: 'Katha',
topics: [{
id: 2,
name: 'Topic 2'
}, {
id: 3,
name: 'Topic 3'
}]
}]
}]
}];
function unravel(obj)
{
var out = [];
var added = false;
for(var i in obj) {
if(obj[i] instanceof Array) {
for(var j in obj[i]) {
var r = unravel(obj[i][j]);
for(var k in r) {
var a = {};
for(var key in obj) { // make copy of obj
a[key] = obj[key];
}
a[i] = r[k];
added = true;
out.push(a);
}
}
}
}
if(!added) {
out.push(obj);
}
return out;
}
var op = [];
for(var i in data)
op = op.concat(unravel(data[i]));
console.log(JSON.stringify(op, null, 4));

Categories

Resources