Javascript - How to create filtered nested Array - javascript

I have my array object here:
let businessList = [{
name: "siAdmin",
count: 52,
children: [{
name: "si1",
count: 30,
children: [{
count: 10,
name: "org1-1"
}, {
count: 14,
name: "org1-2"
}, {
name: "org1-3",
count: 6
}]
}, {
name: "si2",
count: 22,
children: [{
name: "org2-1",
count: 22
}]
}]
}]
I want to make make a filtered list if count > 10, which would be like:
filteredList = [{
name: "siAdmin",
count: 52,
children: [{
name: "si1",
count: 30,
children: [{
count: 14,
name: "org1-2"
}]
}, {
name: "si2",
count: 22,
children: [{
name: "org2-1",
count: 22
}]
}]
}]
How can I achieve this result?
And if condition changes to count > 23, it would be like:
filteredList = [{
name: "siAdmin",
count: 52,
children: [{
name: "si1",
count: 30,
children: []
}]
}]

You can use recursion like this,
let businessList = [{
name: "siAdmin",
count: 52,
children: [{
name: "si1",
count: 30,
children: [{
count: 10,
name: "org1-1"
}, {
count: 14,
name: "org1-2"
}, {
name: "org1-3",
count: 6
}]
}, {
name: "si2",
count: 22,
children: [{
name: "org2-1",
count: 22
}]
}]
}];
const filteredArray = (arr, countLimit) => {
return arr.filter(item => {
if(item.hasOwnProperty('children')) {
item.children = filteredArray(item.children, countLimit);
}
return item.count > countLimit;
})
};
console.log(filteredArray(JSON.parse(JSON.stringify(businessList)), 10));
console.log(filteredArray(JSON.parse(JSON.stringify(businessList)), 23));
console.log(businessList);

let businessList = [{
name: "siAdmin",
count: 52,
children: [{
name: "si1",
count: 30,
children: [{
count: 10,
name: "org1-1"
}, {
count: 14,
name: "org1-2"
}, {
name: "org1-3",
count: 6
}]
}, {
name: "si2",
count: 22,
children: [{
name: "org2-1",
count: 22
}]
}]
}]
function getData(input, number){
let len = input.length;
let ans = [];
for(let i = 0; i < len; i++){
if(input[i].count >= number){
if(input[i].children){
let data = getData(input[i].children,number);
//ans.push(input[i]);
input[i].children = data;
ans.push(input[i])
}
else{
ans.push(input[i]);
}
}
}
return ans;
}
getData(businessList,10)
getData(businessList,23)
above function should work

I finally find the solution without breaking the original object, here's my code:
let businessList = [{
name: "siAdmin",
count: 52,
children: [{
name: "si1",
count: 30,
children: [{
count: 10,
name: "org1-1"
}, {
count: 14,
name: "org1-2"
}, {
name: "org1-3",
count: 6
}]
}, {
name: "si2",
count: 22,
children: [{
name: "org2-1",
count: 22
}]
}]
}];
function filteredBusiness(businessArr, count) {
let arr = [];
businessArr.forEach((business) => {
let index = 0;
let businessMatched = business.count > count
if (businessMatched) {
let {
children,
...dataWithoutChildren
} = business;
arr.push({
...dataWithoutChildren
});
index = arr.length - 1;
let hasChildren = business.children;
if (hasChildren) {
// arr[index].children = [];
//check children matched
let nextBusinessArr = filteredBusiness(
business.children,
count
);
if (nextBusinessArr) {
arr[index].children = nextBusinessArr;
}
}
}
})
return arr;
}
console.log(filteredBusiness(businessList, 10))

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)

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));

Match element with array of object and push to new Array

Suppose I have an array of object as,
const attachmentData = [{name: 'Suman Baidh',attachment: ["123","456"]},
{name: 'John Sigma',attachment: ["789","101112]},
{name: 'Binay', attachment: ["131415","161718","192021]}]
And another array of object as,
const attachmentDetail = [{"id":"123",details:{"cost":10,"quantity":20}},
{"id":"456",details: {"cost":15,"quantity":28}},
{"id":"789",details:{"cost":4,"quantity":9}},
{"id":"101112",details:{"cost":40,"quantity":2}},
{"id":"131415",details:{"cost":12,"quantity":9}},
{"id":"161718",details:{"cost":45,"quantity":2}},
{"id":"192021",details:{"cost":120,"quantity":1}}]
I want the O/P as: Such that the id which is matched with attachmentDetail also has name along with it and pushed to new array.
[{"name":"Suman Baidh","id":"123","cost":10,"quantity":20},
{"name":"Suman Baidh","id":"456","cost":15,"quantity":28},
{"name":"John Sigma","id":"789","cost":4,"quantity":9} ,
{"name":"John Sigma","id":"101112","cost":40,"quantity":2},
{"name":"Binay","id":"131415","cost":12,"quantity":9},
{"name":"Binay","id":"161718","cost":45,"quantity":2},
{"name":"Binay","id":"192021","cost":120,"quantity":1}]
For this I tried as,
let newArray = []
for(let i = 0;i<attachmentData.length;i++)}{
for(let j = 0;j<attachmentData[i].attachment.length;j++){
if(attachmentData[i].attachment[j] == attachmentDetail.id){
newArray.push(...attachmentData[i], ... attachmentData[i].attachment[j]
}
}
}
On console.log(newArray) , its giving me not the answer I wanted.
If anyone needs any further information, please let me know. Any suggestion would be really helpful.
Try this,
const attachmentData = [
{ name: "Suman Baidh", attachment: ["123", "456"] },
{ name: "John Sigma", attachment: ["789", "101112"] },
{ name: "Binay", attachment: ["131415", "161718", "192021"] },
];
const attachmentDetail = [
{ id: "123", details: { cost: 10, quantity: 20 } },
{ id: "456", details: { cost: 15, quantity: 28 } },
{ id: "789", details: { cost: 4, quantity: 9 } },
{ id: "101112", details: { cost: 40, quantity: 2 } },
{ id: "131415", details: { cost: 12, quantity: 9 } },
{ id: "161718", details: { cost: 45, quantity: 2 } },
{ id: "192021", details: { cost: 120, quantity: 1 } },
];
let newArr = [];
attachmentData.forEach(({name, attachment}) => {
attachment.forEach((id) => {
const { details: { cost, quantity } } = attachmentDetail.find((item) => item.id === id)
newArr.push({ name, id, cost, quantity})
})
})
console.log(newArr)
NOTE: Try to use find, map, forEach, filter functions to simplify the for loop whenever possible.
The problem is in the line:
if (attachmentData[i].attachment[j] === attachmentDetail.id) {
Here attachmentDetail is an array. To access its element you need to use attachmentDetail[index].id.
You will need to loop through it to match the id from attachmentData.
const attachmentData = [{name: 'Suman Baidh', attachment: ["123", "456"]},
{name: 'John Sigma', attachment: ["789", "101112"]},
{name: 'Binay', attachment: ["131415", "161718", "192021"]}];
const attachmentDetail = [{"id": "123", details: {"cost": 10, "quantity": 20}},
{"id": "456", details: {"cost": 15, "quantity": 28}},
{"id": "789", details: {"cost": 4, "quantity": 9}},
{"id": "101112", details: {"cost": 40, "quantity": 2}},
{"id": "131415", details: {"cost": 12, "quantity": 9}},
{"id": "161718", details: {"cost": 45, "quantity": 2}},
{"id": "192021", details: {"cost": 120, "quantity": 1}}];
let newArray = []
for (let i = 0; i < attachmentData.length; i++) {
for (let j = 0; j < attachmentData[i].attachment.length; j++) {
for (let k = 0; k < attachmentDetail.length; ++k) {
if (attachmentData[i].attachment[j] === attachmentDetail[k].id) {
newArray.push({
name: attachmentData[i].name,
id: attachmentDetail[k].id,
...attachmentDetail[k].details
});
}
}
}
}
console.log(newArray);
Or
const attachmentData = [{name: 'Suman Baidh', attachment: ["123", "456"]},
{name: 'John Sigma', attachment: ["789", "101112"]},
{name: 'Binay', attachment: ["131415", "161718", "192021"]}];
const attachmentDetail = [{"id": "123", details: {"cost": 10, "quantity": 20}},
{"id": "456", details: {"cost": 15, "quantity": 28}},
{"id": "789", details: {"cost": 4, "quantity": 9}},
{"id": "101112", details: {"cost": 40, "quantity": 2}},
{"id": "131415", details: {"cost": 12, "quantity": 9}},
{"id": "161718", details: {"cost": 45, "quantity": 2}},
{"id": "192021", details: {"cost": 120, "quantity": 1}}];
const newArray = attachmentDetail.map(x => ({
name: attachmentData.filter(y => y.attachment.includes(x.id))[0].name,
id: x.id, ...x.details
}));
console.log(newArray);
Output
[
{ name: 'Suman Baidh', id: '123', cost: 10, quantity: 20 },
{ name: 'Suman Baidh', id: '456', cost: 15, quantity: 28 },
{ name: 'John Sigma', id: '789', cost: 4, quantity: 9 },
{ name: 'John Sigma', id: '101112', cost: 40, quantity: 2 },
{ name: 'Binay', id: '131415', cost: 12, quantity: 9 },
{ name: 'Binay', id: '161718', cost: 45, quantity: 2 },
{ name: 'Binay', id: '192021', cost: 120, quantity: 1 }
]
I think that something like this will work!
const attachmentData = [
{ name: "Suman Baidh", attachment: ["123", "456"] },
{ name: "John Sigma", attachment: ["789", "101112"] },
{ name: "Binay", attachment: ["131415", "161718", "192021"] },
];
const attachmentDetail = [
{ id: "123", details: { cost: 10, quantity: 20 } },
{ id: "456", details: { cost: 15, quantity: 28 } },
{ id: "789", details: { cost: 4, quantity: 9 } },
{ id: "101112", details: { cost: 40, quantity: 2 } },
{ id: "131415", details: { cost: 12, quantity: 9 } },
{ id: "161718", details: { cost: 45, quantity: 2 } },
{ id: "192021", details: { cost: 120, quantity: 1 } },
];
const newArray = attachmentDetail.map((detail) => {
const data = attachmentData.find((data) => data.attachment.includes(detail.id));
return {name: data.name, id: detail.id, ...detail.details}
})
If we want to deal with two arrays(specially for large sets of data), It's always good to convert one array to object(hash) and iterate over the other to find the matching.
const attachmentData = [{name: 'Suman Baidh',attachment: ["123","456"]}, {name: 'John Sigma',attachment: ["789","101112"]}, {name: 'Binay', attachment: ["131415","161718","192021"]}]
const attachmentDetail = [{"id":"123",details:{"cost":10,"quantity":20}}, {"id":"456",details: {"cost":15,"quantity":28}}, {"id":"789",details:{"cost":4,"quantity":9}}, {"id":"101112",details:{"cost":40,"quantity":2}}, {"id":"131415",details:{"cost":12,"quantity":9}}, {"id":"161718",details:{"cost":45,"quantity":2}}, {"id":"192021",details:{"cost":120,"quantity":1}}];
function customMerge(data, attachments) {
const hashById = attachments.reduce((acc, ele) => {
acc[ele.id] = ele;
return acc;
}, {});
return data.reduce((acc, {attachment, name}) => {
return acc.concat(attachment.map(id => ({name, id, details: hashById[id].details})));
},[]);
}
console.log(customMerge(attachmentData, attachmentDetail))
const attachmentData = [
{ name: 'Suman Baidh', attachment: [ '123', '456' ] },
{ name: 'John Sigma', attachment: [ '789', '101112' ] },
{ name: 'Binay', attachment: [ '131415', '161718', '192021' ] },
];
const attachmentDetail = [
{ id: '123', details: { cost: 10, quantity: 20 } },
{ id: '456', details: { cost: 15, quantity: 28 } },
{ id: '789', details: { cost: 4, quantity: 9 } },
{ id: '101112', details: { cost: 40, quantity: 2 } },
{ id: '131415', details: { cost: 12, quantity: 9 } },
{ id: '161718', details: { cost: 45, quantity: 2 } },
{ id: '192021', details: { cost: 120, quantity: 1 } },
];
const newArray = [];
for (let i = 0; i < attachmentData.length; i++) {
const { attachment } = attachmentData[i];
for (let j = 0; j < attachment.length; j++) {
attachmentDetail.some(element => {
if (element.id === attachment[j]) {
newArray.push({ name: attachmentData[i].name, ...element });
return true;
}
});
}
}
console.log(newArray);
You can first create a Map whose keys are the attachment ids and value is the name corresponding to that attachment.
Then loop over attachmentDetail array and just add the name using the Map created.
const
attachmentData = [{ name: "Suman Baidh", attachment: ["123", "456"] }, { name: "John Sigma", attachment: ["789", "101112"] }, { name: "Binay", attachment: ["131415", "161718", "192021"] }],
attachmentDetail = [{ id: "123", details: { cost: 10, quantity: 20 } }, { id: "456", details: { cost: 15, quantity: 28 } }, { id: "789", details: { cost: 4, quantity: 9 } }, { id: "101112", details: { cost: 40, quantity: 2 } }, { id: "131415", details: { cost: 12, quantity: 9 } }, { id: "161718", details: { cost: 45, quantity: 2 } }, { id: "192021", details: { cost: 120, quantity: 1 } }],
map = attachmentData.reduce((m, o) => (o.attachment.map((a) => m.set(a, o.name)), m), new Map()),
res = attachmentDetail.map(({ id, details }) => (name => ({ id, name, ...details }))(map.get(id)));
console.log(res);

pushing a string into array return a number and not the actual string?

I am trying pushing the name but in the console log I see just a number and not the actual name
What am i doing wrong??
const cartItems = [{
id: 1,
name: "Soup",
price: 3,
category: "starters",
count: 1
},
{
id: 2,
name: "Pâté",
price: 5,
category: "starters",
count: 1
},
{
id: 9,
name: "Sticky toffee",
price: 18,
category: "desserts",
count: 1
}
]
var dishesArray = [];
var groupByCategory = []
cartItems.reduce(function(res, value) {
if (!res[value.category]) {
res[value.category] = {
category: value.category,
count: 0,
dishes: dishesArray.push(value.name), // problem here
};
groupByCategory.push(res[value.category]);
}
res[value.category].count += value.count;
return res;
}, {});
console.log(groupByCategory)
Expected output
[{category: "starters", count: 2, dishes:["Soup","Pâté"]},
{category: "desserts", count: 1, dishes:["Sticky toffee"]}]
As mentioned, a push returns an int
I believe you are looking for this much shortened reduce
const cartItems = [
{ id: 1, name: "Soup", price: 3, category: "starters", count: 1 },
{ id: 2, name: "Pâté", price: 5, category: "starters", count: 1 },
{ id: 9, name: "Sticky toffee", price: 18, category: "desserts", count: 1}
];
const groupByCategory = cartItems.reduce(function(res, value) {
const cat = value.category;
res[cat] = res[cat] || { category: cat, count: 0, dishes: [] };
res[cat].count += value.count;
res[cat].dishes.push(value.name)
return res;
}, {});
console.log(groupByCategory)

How to sort an array by frequency of occurrence?

I've array like this :
people = [
{id:1,name:'abc',age:18},
{id:2,name:'abcd',age:20},
{id:3,name:'abce',age:18},
{id:4,name:'abcf',age:18},
{id:5,name:'abcg',age:21},
{id:6,name:'abch',age:20},
{id:7,name:'abci',age:17},
]
Now I want Sorting an array order by frequency of occurence(age) in JavaScript.
Output like this:
people = [
{id:1,name:'abc',age:18},
{id:3,name:'abce',age:18},
{id:4,name:'abcf',age:18},
{id:2,name:'abcd',age:20},
{id:6,name:'abch',age:20},
{id:5,name:'abcg',age:21},
{id:7,name:'abci',age:17},
]
So how I can do it ?
I've tried follow answer of Nina Scholz but i've a bug like this.
var people = [{ id: 1, name: 'abc', age: 18 }, { id: 2, name: 'abcd', age: 20 }, { id: 3, name: 'abce', age: 18 }, { id: 4, name: 'abcf', age: 18 }, { id: 5, name: 'abcg', age: 21 }, { id: 6, name: 'abch', age: 20 }, { id: 7, name: 'abcg', age: 21 }, { id: 8, name: 'abci', age: 17 }],
count = people.reduce((r, { age }) => (r[age] = (r[age] || 0) + 1, r), {});
people.sort((a, b) => count[b.age] - count[a.age]);
console.log(people);
Output is :
people = [
{id:1,name:'abc',age:18},
{id:3,name:'abce',age:18},
{id:4,name:'abcf',age:18},
{id:2,name:'abcd',age:20},
{id:5,name:'abcg',age:21},
{id:6,name:'abch',age:20},
{id:5,name:'abcg',age:21},
{id:7,name:'abci',age:17},
]
Just count ages and sort descending by the count.
var people = [{ id: 1, name: 'abc', age: 18 }, { id: 2, name: 'abcd', age: 20 }, { id: 3, name: 'abce', age: 18 }, { id: 4, name: 'abcf', age: 18 }, { id: 5, name: 'abcg', age: 21 }, { id: 6, name: 'abch', age: 20 }, { id: 7, name: 'abci', age: 17 }],
count = people.reduce((r, { age }) => (r[age] = (r[age] || 0) + 1, r), {});
people.sort((a, b) => count[b.age] - count[a.age]);
console.log(people);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For sorting by count and age, add a logical OR || along with the delta of the ages.
var people = [{ id: 1, name: 'abc', age: 18 }, { id: 2, name: 'abcd', age: 20 }, { id: 3, name: 'abce', age: 18 }, { id: 4, name: 'abcf', age: 18 }, { id: 5, name: 'abcg', age: 21 }, { id: 6, name: 'abch', age: 20 }, { id: 7, name: 'abcg', age: 21 }, { id: 8, name: 'abci', age: 17 }],
count = people.reduce((r, { age }) => (r[age] = (r[age] || 0) + 1, r), {});
people.sort((a, b) =>
count[b.age] - count[a.age] ||
b.age - a.age
);
console.log(people);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Try this:
let people = [{ id: 1, name: 'abc', age: 18 }, { id: 2, name: 'abcd', age: 20 }, { id: 3, name: 'abce', age: 18 }, { id: 4, name: 'abcf', age: 18 }, { id: 5, name: 'abcg', age: 21 }, { id: 6, name: 'abch', age: 20 }, { id: 7, name: 'abci', age: 17 }];
let tmpAge = {};
for (let i = 0; i < people.length; i++) {
if (!tmpAge[people[i].age]) {
tmpAge[people[i].age] = 1;
} else {
tmpAge[people[i].age]++;
}
}
people.sort((a, b) => tmpAge[b.age] - tmpAge[a.age]);
console.log(people);
const people = [
{ id: 1, name: 'abc', age: 18 },
{ id: 2, name: 'abcd', age: 20 },
{ id: 3, name: 'abce', age: 18 },
{ id: 4, name: 'abcf', age: 18 },
{ id: 5, name: 'abcg', age: 21 },
{ id: 6, name: 'abch', age: 20 },
{ id: 7, name: 'abci', age: 17 },
];
const agesFrequency = people.reduce((previousValue, currentValue) => {
const { age } = currentValue;
return {
...previousValue,
[age]: (
previousValue[age] || 0
) + 1,
};
}, {});
people.sort((
(a, b) =>
agesFrequency[b.age] - agesFrequency[a.age]
));
console.log(people);
I solved it . Change function sort to
people.sort((a, b) => {
if (count[b.age] === count[a.age]) {
if (b.age < a.age) {
return -1;
}
if (b.age > a.age) {
return 1;
}
return 0;
} else if (count[b.age] < count[a.age]) {
return -1;
}
});
Posted on behalf of OP

Categories

Resources