Filter array object by name - javascript

I have array object like this, can you help me?
[{id: 1, name: "contractor"},
{id: 2, name: "owner", },
{id: 3, name: "manager", },
{id: 4, name: "customer", },
{id: 5, name: "admin",}]
I want a format like that:
if admin
[admin:
{id: 1, name: "contractor"},
{id: 2, name: "owner", },
{id: 3, name: "manager", },
{id: 4, name: "customer", }]
if contractor
[contractor:
{id: 2, name: "owner", },
{id: 3, name: "manager", },
{id: 4, name: "customer", }]
if owner
[owner:
{id: 3, name: "manager", },
{id: 4, name: "customer", }]
if manager
[manager:
{id: 4, name: "customer", }]

Based on the comments, i guess you need this
let array = [
{id: 1, name: "contractor"},
{id: 2, name: "owner"},
{id: 3, name: "manager"},
{id: 4, name: "customer"},
{id: 5, name: "admin"}
]
const admin = { admin: array.filter(obj => obj.id < 5) }
const contractor = { contractor: array.filter(obj => [2, 3, 4].includes(obj.id)) }
const owner = { owner: array.filter(obj => [3, 4].includes(obj.id)) }
const manager = { manager: array.filter(obj => obj.id === 4) }
console.log(admin, contractor, owner, manager)

IF you want to make it so it will only generate the array if it is included in the name, then you can use array.reduce
const array = [
{id: 1, name: "contractor"},
{id: 2, name: "owner"},
{id: 3, name: "manager"},
{id: 4, name: "customer"},
{id: 5, name: "admin"}
];
const objects = array.reduce((prev, curr) => {
if (prev[curr.name]) {
return {
...prev,
[prev[curr.name]]: prev[curr.name].concat(curr),
}
}
return {
...prev,
[curr.name]: [curr]
}
}, {});
console.log(objects);

You have to sort the data first, as you can see the below code. I hope this would be helpful. thanks
const array = [
{ id: 1, name: "contractor", sort: 2 },
{ id: 2, name: "owner", sort: 3 },
{ id: 3, name: "manager", sort: 4 },
{ id: 4, name: "customer", sort: 5 },
{ id: 5, name: "admin", sort: 1 }
];
let nameArr = [];
let arr = [];
let newArray = [];
const sortedData = array.sort((a, b) => a.sort - b.sort);
sortedData.forEach(ele => {
array.forEach(item => {
if (item.name !== ele.name) {
if (newArray.length) {
if (!nameArr.includes(item.name) && (item.name !== ele.name)) {
arr.push(item);
}
} else {
arr.push(item);
}
}
})
newArray.push({ [ele.name]: arr });
nameArr.push(ele.name);
arr = []
})
console.log(newArray)
Result will be this:
[
{
"admin": [
{
"id": 1,
"name": "contractor",
"sort": 2
},
{
"id": 2,
"name": "owner",
"sort": 3
},
{
"id": 3,
"name": "manager",
"sort": 4
},
{
"id": 4,
"name": "customer",
"sort": 5
}
]
},
{
"contractor": [
{
"id": 2,
"name": "owner",
"sort": 3
},
{
"id": 3,
"name": "manager",
"sort": 4
},
{
"id": 4,
"name": "customer",
"sort": 5
}
]
},
{
"owner": [
{
"id": 3,
"name": "manager",
"sort": 4
},
{
"id": 4,
"name": "customer",
"sort": 5
}
]
},
{
"manager": [
{
"id": 4,
"name": "customer",
"sort": 5
}
]
},
{
"customer": []
}
]

Related

count object based on status and shop using javascript?

I have the following JSON array I want to create a new field in every object which will be a count of the object
we have to get a count based on status, shop, and name(ownerDetails)
How can I achieve this and I have added my expected output below
var items = [
{
"id": 1,
"status": "ORANGE",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id": 2,
"status": "GREEN",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id": 3,
"status": "ORANGE",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id": 4,
"status": "YELLOW",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id": 5,
"status": "RED",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id":6,
"status": "GREEN",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id": 7,
"status": "GREEN",
"Shop":"XYZ",
"ownerDetails":[ {"name":"test2","address":"test2"}]
},
{
"id": 8,
"status": "ORANGE",
"Shop":"XYZ",
"ownerDetails":[ {"name":"test2","address":"test2"}]
},
{
"id": 9,
"status": "YELLOW",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id": 10,
"status": "GREEN",
"Shop":"EFG",
"ownerDetails":[ {"name":"test3","address":"test3"}]
},
{
"id": 11,
"status": "GREEN",
"Shop":"EFG",
"ownerDetails":[ ]
}
]
Expected output: So based on each shop, status and name(ownerDetails) we have to count the object
[
{
"id": 1,
"status": "ORANGE"
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}],
"Count": 2
},
{
"id": 2,
"status": "GREEN"
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}],
"Count": 2
},
{
"id": 3,
"status": "ORANGE"
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}],
"Count": 2
},
{
"id": 4,
"status": "YELLOW"
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}],
"Count": 2
},
{
"id": 5,
"status": "RED"
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}],
"Count": 1
},
{
"id":6,
"status": "GREEN"
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}],
"Count": 2
},
{
"id": 7,
"status": "GREEN"
"Shop":"XYZ",
"ownerDetails":[ {"name":"test2","address":"test2"}],
"Count": 1
},
{
"id": 8,
"status": "ORANGE"
"Shop":"XYZ",
"ownerDetails":[ {"name":"test2","address":"test2"}],
"Count": 1
},
{
"id": 9,
"status": "YELLOW"
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}],
"Count": 2
},
{
"id": 10,
"status": "GREEN"
"Shop":"EFG"
"ownerDetails":[ {"name":"test3","address":"test3"}],
"Count": 1
},
{
"id": 11,
"status": "GREEN",
"Shop":"EFG",
"ownerDetails":[ ],
"Count": 1
}
]
Plese see demo
Thanks #Nico_ for your and #Parth Ravalhelp
Below code is not working when "ownerDetails":[ ] and I got the below error Cannot read properties of undefined (reading 'name') in console
code :
const itemsWithCount = items.map(item => ({
...item,
Count: items.filter(({ status, Shop ,ownerDetails: [{ name }]}) => item.status === status && item.Shop === Shop && item.ownerDetails[0].name === name).length
}));
console.log(itemsWithCount)
Deconstruction of a not defined object
/**
* Problem: The deconstructed object is not defined.
*
* This will throw: TypeError: Cannot read properties of undefined (reading 'name')
*
* This is roughly equivalent of doing const { name } = undefined
*/
const [{ name }] = [];
/**
* Solution: Assign a default value when the deconstructed object is not defined.
*
* If the deconstructing object is undefined,
* assign an empty object as the default value
*/
const [{ name } = {}] = [];
Accessing a property of an undefined object
If you don't check that the ownerDetails array isn't empty before comparing item.ownerDetails[0].name === name, you might end up trying to access a property of an object that doesn't exist. This will result in a TypeError like above.
To deal with this situation, you must:
Verify that there is at least one element in item.ownerDetails;
Verify that name property exists on the first element;
If the tests passed, returns the value of the name property for the first element of ownerDetails. Otherwise, you must provide a default value.
Working example
const items = [
{ id: 1, status: 'ORANGE', Shop: 'ABC', ownerDetails: [{ name: 'test1', address: 'test1' }] },
{ id: 2, status: 'GREEN', Shop: 'ABC', ownerDetails: [{ name: 'test1', address: 'test1' }] },
{ id: 3, status: 'ORANGE', Shop: 'ABC', ownerDetails: [{ name: 'test1', address: 'test1' }] },
{ id: 4, status: 'YELLOW', Shop: 'ABC', ownerDetails: [{ name: 'test1', address: 'test1' }] },
{ id: 5, status: 'RED', Shop: 'ABC', ownerDetails: [{ name: 'test1', address: 'test1' }] },
{ id: 6, status: 'GREEN', Shop: 'ABC', ownerDetails: [{ name: 'test1', address: 'test1' }] },
{ id: 7, status: 'GREEN', Shop: 'XYZ', ownerDetails: [{ name: 'test2', address: 'test2' }] },
{ id: 8, status: 'ORANGE', Shop: 'XYZ', ownerDetails: [{ name: 'test2', address: 'test2' }] },
{ id: 9, status: 'YELLOW', Shop: 'ABC', ownerDetails: [{ name: 'test1', address: 'test1' }] },
{ id: 10, status: 'GREEN', Shop: 'EFG', ownerDetails: [{ name: 'test3', address: 'test3' }] },
{ id: 11, status: 'GREEN', Shop: 'EFG', ownerDetails: [] }
];
const itemsWithCount = items.map(item => ({
...item,
/**
* If the first element of ownerDetails is not defined,
* assign an empty object as the default value for the first
* element of ownerDetails array.
*/
Count: items.filter(({ status, Shop, ownerDetails: [{ name } = {}] }) =>
item.status === status &&
item.Shop === Shop &&
(
(
/**
* 1. Check if ownerDetails is not empty.
*/
item.ownerDetails.length &&
/**
* 2. Check if the first element of item.ownerDetails has a name property.
*
* ESLint best practice:
* ------------------------------------------------------
* Disallow calling some Object.prototype methods directly on objects.
* For more details, see https://eslint.org/docs/rules/no-prototype-builtins
* ------------------------------------------------------
*/
Object.prototype.hasOwnProperty.call(item.ownerDetails[0], 'name') &&
/**
* 3. Accessing and returning name property.
*/
item.ownerDetails[0].name
/**
* Else, compare undefined with name property.
*/
) || undefined
) === name
).length
}));
console.log(itemsWithCount)
Output
[
{ Count: 2, id: 1, ownerDetails: [{ address: 'test1', name: 'test1' }], Shop: 'ABC', status: 'ORANGE' },
{ Count: 2, id: 2, ownerDetails: [{ address: 'test1', name: 'test1' }], Shop: 'ABC', status: 'GREEN' },
{ Count: 2, id: 3, ownerDetails: [{ address: 'test1', name: 'test1' }], Shop: 'ABC', status: 'ORANGE' },
{ Count: 2, id: 4, ownerDetails: [{ address: 'test1', name: 'test1' }], Shop: 'ABC', status: 'YELLOW' },
{ Count: 1, id: 5, ownerDetails: [{ address: 'test1', name: 'test1' }], Shop: 'ABC', status: 'RED' },
{ Count: 2, id: 6, ownerDetails: [{ address: 'test1', name: 'test1' }], Shop: 'ABC', status: 'GREEN' },
{ Count: 1, id: 7, ownerDetails: [{ address: 'test2', name: 'test2' }], Shop: 'XYZ', status: 'GREEN' },
{ Count: 1, id: 8, ownerDetails: [{ address: 'test2', name: 'test2' }], Shop: 'XYZ', status: 'ORANGE' },
{ Count: 2, id: 9, ownerDetails: [{ address: 'test1', name: 'test1' }], Shop: 'ABC', status: 'YELLOW' },
{ Count: 1, id: 10, ownerDetails: [{ address: 'test3', name: 'test3' }], Shop: 'EFG', status: 'GREEN' },
{ Count: 1, id: 11, ownerDetails: [], Shop: 'EFG', status: 'GREEN' }
]
var items = [{
"id": 1,
"status": "ORANGE",
"Shop": "ABC",
"ownerDetails": [{
"name": "test1",
"address": "test1"
}]
},
{
"id": 2,
"status": "GREEN",
"Shop": "ABC",
"ownerDetails": [{
"name": "test1",
"address": "test1"
}]
},
{
"id": 3,
"status": "ORANGE",
"Shop": "ABC",
"ownerDetails": [{
"name": "test1",
"address": "test1"
}]
},
{
"id": 4,
"status": "YELLOW",
"Shop": "ABC",
"ownerDetails": [{
"name": "test1",
"address": "test1"
}]
},
{
"id": 5,
"status": "RED",
"Shop": "ABC",
"ownerDetails": [{
"name": "test1",
"address": "test1"
}]
},
{
"id": 6,
"status": "GREEN",
"Shop": "ABC",
"ownerDetails": [{
"name": "test1",
"address": "test1"
}]
},
{
"id": 7,
"status": "GREEN",
"Shop": "XYZ",
"ownerDetails": [{
"name": "test2",
"address": "test2"
}]
},
{
"id": 8,
"status": "ORANGE",
"Shop": "XYZ",
"ownerDetails": [{
"name": "test2",
"address": "test2"
}]
},
{
"id": 9,
"status": "YELLOW",
"Shop": "ABC",
"ownerDetails": [{
"name": "test1",
"address": "test1"
}]
},
{
"id": 10,
"status": "GREEN",
"Shop": "EFG",
"ownerDetails": [{
"name": "test3",
"address": "test3"
}]
}
];
var mapData = items.map((data) => {
var getList = items.filter(word => word.Shop == data.Shop).length;
return {
id: data.id,
status: data.status,
Shop: data.Shop,
text: data.ownerDetails,
Count: getList
};
});
console.log(mapData);
Note:- Map Data and Counted Similar Shops....
Looping through the array for each element is not an efficient way to go about it. A cleaner and more efficient way would be to create an object with keys as the combination of the values you need to compare.
Following should help:
let items = [
{"id":1,"status":"ORANGE","Shop":"ABC","ownerDetails":[{"name":"test1","address":"test1"}]},
{"id":2,"status":"GREEN","Shop":"ABC","ownerDetails":[{"name":"test1","address":"test1"}]},
{"id":3,"status":"ORANGE","Shop":"ABC","ownerDetails":[{"name":"test1","address":"test1"}]},
{"id":4,"status":"YELLOW","Shop":"ABC","ownerDetails":[{"name":"test1","address":"test1"}]},
{"id":5,"status":"RED","Shop":"ABC","ownerDetails":[{"name":"test1","address":"test1"}]},
{"id":6,"status":"GREEN","Shop":"ABC","ownerDetails":[{"name":"test1","address":"test1"}]},
{"id":7,"status":"GREEN","Shop":"XYZ","ownerDetails":[{"name":"test2","address":"test2"}]},
{"id":8,"status":"ORANGE","Shop":"XYZ","ownerDetails":[{"name":"test2","address":"test2"}]},
{"id":9,"status":"YELLOW","Shop":"ABC","ownerDetails":[{"name":"test1","address":"test1"}]},
{"id":10,"status":"GREEN","Shop":"EFG","ownerDetails":[{"name":"test3","address":"test3"}]},
{"id":11,"status":"GREEN","Shop":"EFG","ownerDetails":[]}
]
let itemMap = {};
for (const item of items) {
const key = `${item.Shop}_${item.status}_${item.ownerDetails[0]?.name}`;
if (itemMap[key]) {
itemMap[key].push({ ...item, Count: itemMap[key][0].Count+1 });
for (const matchedItem of itemMap[key]) {
matchedItem.Count++;
}
} else {
itemMap[key] = [{ ...item, Count: 1 }];
}
}
let processedItems = [];
for (const items of Object.values(itemMap)) {
for (const item of items) {
processedItems.push(item);
}
}
console.log(processedItems);
Note: This would not work if the order of the objects is to be preserved
You can do it with a map to loop through your array (you need to add some coma before the "Shop" by the way.
const items = [
{
"id": 1,
"status": "ORANGE",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id": 2,
"status": "GREEN",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id": 3,
"status": "ORANGE",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id": 4,
"status": "YELLOW",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id": 5,
"status": "RED",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id":6,
"status": "GREEN",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id": 7,
"status": "GREEN",
"Shop":"XYZ",
"ownerDetails":[ {"name":"test2","address":"test2"}]
},
{
"id": 8,
"status": "ORANGE",
"Shop":"XYZ",
"ownerDetails":[ {"name":"test2","address":"test2"}]
},
{
"id": 9,
"status": "YELLOW",
"Shop":"ABC",
"ownerDetails":[ {"name":"test1","address":"test1"}]
},
{
"id": 10,
"status": "GREEN",
"Shop":"EFG",
"ownerDetails":[ {"name":"test3","address":"test3"}]
},
{
"id": 11,
"status": "GREEN",
"Shop":"EFG",
"ownerDetails":[ ]
}
];
const itemsWithCount = items.map(item => ({
...item,
Count: items.filter(({ status, Shop }) => item.status === status && item.Shop === Shop).length
}));
For each item of your array, you keep the current value of the item (the ...item) and you add a Count property, that will get the count for this item by filtering the array to keep only the item that have the same status and shop and you get the length of that array.

JavaScript lookup: update value of object in array if object key exists in another object array similar to the v-lookup in excel

Just trying to update the dates in array2 if ID matches in array1 so that they are not null.
let array1 = [{"id":1, "date": "23/11/21"}, {"id":2, "date":"20/11/21"}, {"id":3, "date":"15/11/21"}]
let array2 = [{"id":1, "name": "John", "date": null}, {"id":2, "name": "Max", "date": null}, {"id":3, "name": "Peter", "date": null}]
Desired output:
let array2 = [{"id":1, "name": "John", "date":"23/11/21" }, {"id":2, "name": "Max", "date": "20/11/21"}, {"id":3, "name": "Peter", "date": "15/11/21"}]
How do I use a loop with the indexof() method?
You could use a map method to iterate trough the second array, find an element with the same id in the first array and take the date from there:
let array1 = [{
"id": 1,
"date": "23/11/21"
}, {
"id": 2,
"date": "20/11/21"
}, {
"id": 3,
"date": "22/11/15"
}]
let array2 = [{
"id": 1,
"name": "John",
"date": null
}, {
"id": 2,
"name": "Max",
"date": null
}, {
"id": 3,
"name": "Peter",
"date": null
}];
const updated = array2.map(el => {
const isIdInFirstArr = array1.find(e => e.id === el.id);
if (isIdInFirstArr) {
el.date = isIdInFirstArr.date;
}
return el;
})
console.log(updated)
1) You can efficiently achieve this using Map as:
let array1 = [
{ id: 1, date: "23/11/21" },
{ id: 2, date: "20/11/21" },
{ id: 3, date: "15/11/21" },
];
let array2 = [
{ id: 1, name: "John", date: null },
{ id: 2, name: "Max", date: null },
{ id: 3, name: "Peter", date: null },
];
const map = new Map();
array1.forEach((o) => map.set(o.id, o.date));
let result = array2.map((o) => ({ ...o, date: o.date ?? map.get(o.id) }));
console.log(result);
/* This is not a part of answer. It is just to give the output full height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }
2) You can easily achieve the result using map and find
let array1 = [
{ id: 1, date: "23/11/21" },
{ id: 2, date: "20/11/21" },
{ id: 3, date: "15/11/21" },
];
let array2 = [
{ id: 1, name: "John", date: null },
{ id: 2, name: "Max", date: null },
{ id: 3, name: "Peter", date: null },
];
let result = array2.map(o => ({ ...o, date: o.date ?? array1.find(obj => obj.id === o.id)?.date}));
console.log(result)
/* This is not a part of answer. It is just to give the output full height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to group values from an array of objects by same values with javascript?

I have an array of objects as following
[
0: {department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 1, …}
1: {department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 2, …}
2: {department_ID: 1, department_Name: "HR & Admin", section_ID: 20, section_Name: "HR and Admin", employee_ID: 90, …}
...
]
What I want to achieve is to group values in an array by order same department_ID > same section_ID and finally employee data like this
[
{
department_ID: 6,
department_Name: "Management",
children: [
{
section_ID: 12,
section_Name: "General Management",
children: [
{
employee_ID: 1,
employee_Name: "",
},
{
employee_ID: 2,
employee_Name: "",
},
],
},
],
},
{
department_ID: 1,
department_Name: "HR & Admin",
children: [
{
section_ID: 20,
section_Name: "HR and Admin",
children: [
{
employee_ID: 90,
employee_Name: "",
},
],
},
],
},
];
I've tried
function getUnique() {
var hashObject = {};
let obj = {};
treeviewApiValues.forEach(function (elem) {
var key = elem.department_ID;
if (hashObject[key]) {
hashObject[key] = {
id: elem.department_ID,
name: elem.department_Name,
children: checkSectionID(elem),
};
} else {
hashObject[key] = {
id: elem.department_ID,
name: elem.department_Name,
children: checkSectionID(elem),
};
}
});
function checkSectionID(elem) {
const key = elem.department_ID;
if (obj[key]) {
obj[key].push({
id: elem.section_ID,
name: elem.section_Name,
});
} else {
obj[key] = [
{
id: elem.section_ID,
name: elem.section_Name,
},
];
}
var desiredArray2 = Object.values(obj);
return desiredArray2;
}
var desiredArray = Object.values(hashObject);
}
This is a messy function, but I get
[
0: {department_ID: 1, department_Name: "HR & Admin", children: Array(7)}
1: {department_ID: 2, department_Name: "ELV Systems Installation & Service", children: Array(7)}
]
Children array is something wrong and not having array of same department_ID and I also need to get the employee data under same section_ID.
If anyone could help me, i would be so much appreciated.
Full code can be found here https://codesandbox.io/s/gracious-voice-bbmsy?file=/src/App.js
You could take a nested approach with an array for the grouping levels.
This solution removes unwanted properties from the object and pushes the final object to the most nested children array.
This solution works for an arbitrary count of levels.
const
data = [{ department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 1 }, { department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 2 }, { department_ID: 1, department_Name: "HR & Admin", section_ID: 20, section_Name: "HR and Admin", employee_ID: 90 }],
groups = [['department_ID', 'department_Name'], ['section_ID', 'section_Name']],
result = data.reduce((r, o) => {
groups
.reduce((group, keys) => {
let temp = group.find(q => q[keys[0]] === o[keys[0]]);
if (!temp) group.push(temp = { ...Object.fromEntries(keys.map(k => [k, o[k]])), children: [] });
keys.forEach(k => ({ [k]: _, ...o} = o));
return temp.children;
}, r)
.push(o);
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
May be it solve your task
let list = [
{department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 1, …},
{department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 2, …},
{department_ID: 1, department_Name: "HR & Admin", section_ID: 20, section_Name: "HR and Admin", employee_ID: 90, …}
...
];
let vals = [];
list.map(v=>{
vals[v.department_ID] || (vals[v.department_ID] = {
department_ID: v.department_ID,
department_Name: v.department_Name,
children: []
});
vals[v.department_ID].children[v.section_ID] ||
(vals[v.department_ID].children[v.section_ID] = {
section_ID: v.section_ID,
section_Name: v.section_Name,
children: []
});
vals[v.department_ID].children[v.section_ID].children.push({
employee_ID: v.employee_ID,
employee_Name: v.employee_Name
});
});
vals = vals.filter(e=>!!e);
let result = vals.map(e=>{
e.children = e.children.filter(v=>!!v);
return e;
});
You can use reduce() and find() as follows:
const arr = [
{department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 1, employee_name: 'john'},
{department_ID: 6, department_Name: "Management", section_ID: 12, section_Name: "General Management", employee_ID: 2, employee_name: 'avi'},
{department_ID: 1, department_Name: "HR & Admin", section_ID: 20, section_Name: "HR and Admin", employee_ID: 90, employee_name: 'jennifer'}
]
const res = arr.reduce((acc, curr) => {
const obj = acc.find(item => item.department_ID === curr.department_ID && item?.children[0]?.section_ID === curr.section_ID);
if(obj) {
obj.children[0].children.push({ employee_ID: curr.employee_ID, employee_name: curr.employee_name});
} else {
acc.push({
department_ID: curr.department_ID,
department_Name: curr.department_Name,
children: [
{
section_ID: curr.section_ID,
section_Name: curr.section_Name,
children: [{
employee_ID: curr.employee_ID,
employee_name: curr.employee_name
}]
}
]
})
}
return acc;
}, []);
console.log(res);

How to do child level filtering of JSON data using Lodash

I have below JSON data set
[
{
"campaignId": 111,
"campaignCategory": "Diabetes",
"result": [
{
"campaignType": 1,
"name": "tes1"
},
{
"campaignType": 1,
"name": "test22"
},
{
"campaignType": 3,
"name": "test33"
}
]
},
{
"campaignId": 222,
"campaignCategory": "Orthopedic",
"result": [
{
"campaignType": 1,
"name": "Orthopedic"
}
]
},
{
"campaignId": 333,
"campaignCategory": "Cardiology",
"result": [
{
"campaignType": 3,
"name": "Cardiology"
},
{
"campaignType": 1,
"name": "Cardiology 123"
}
]
}
]
I have tired below filter but that doesn't returned desired data.
_.filter(summary, function (data) {
return (post, _.filter(data.result, {'campaignType': 3}));
I want to get below data after filtering applied.
[{ campaignId: 111, campaignCategory: 'Diabetes', result: [{
campaignType: 3, name: 'test33'
}] },
{ campaignId: 333, campaignCategory: 'Cardiology', result: [{
campaignType: 3, name: 'Cardiology'
}] } ];
Here all the nodes are showing which have campaignType: 3.
Lodash or pure java-script based solution will work.
You can use reduce to find objects which have a .result item with a campaignType of 3, and if found, push them to the accumulator array:
const getOutput = () => {
const output = arr.reduce((a, item) => {
const foundResults = item.result.filter(({ campaignType }) => campaignType === 3);
if (foundResults.length) {
a.push({ ...item, result: foundResults });
}
return a;
}, []);
console.log(output);
};
const arr = [{
campaignId: 111,
campaignCategory: 'Diabetes',
result: [{
campaignType: 1,
name: 'tes1'
}, {
campaignType: 1,
name: 'test22'
}, {
campaignType: 3,
name: 'test33'
}]
},
{
campaignId: 222,
campaignCategory: 'Orthopedic',
result: [{
campaignType: 1,
name: 'Orthopedic'
}]
},
{
campaignId: 333,
campaignCategory: 'Cardiology',
result: [{
campaignType: 3,
name: 'Cardiology'
},
{
campaignType: 1,
name: 'Cardiology 123'
}
]
}
];
getOutput();
You could filter the inner result in advance and take the outer objects if ayn filters elements exists. Then take a new object with a new result.
var data = [{ campaignId: 111, campaignCategory: 'Diabetes', result: [{ campaignType: 1, name: 'tes1' }, { campaignType: 1, name: 'test22' }, { campaignType: 3, name: 'test33' }] }, { campaignId: 222, campaignCategory: 'Orthopedic', result: [{ campaignType: 1, name: 'Orthopedic' }] }, { campaignId: 333, campaignCategory: 'Cardiology', result: [{ campaignType: 3, name: 'Cardiology' }, { campaignType: 1, name: 'Cardiology 123' }] }],
result = data.reduce((r, o) => {
var result = o.result.filter(({ campaignType}) => campaignType === 1);
if (result.length) r.push(Object.assign({}, o, { result }));
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use filter with some and map in vanilla javascript.
var data = [{ campaignId: 111, campaignCategory: 'Diabetes', result: [{
campaignType: 1, name: 'tes1'
},{
campaignType: 1, name: 'test22'
},{
campaignType: 3, name: 'test33'
}] },
{ campaignId: 222, campaignCategory: 'Orthopedic', result: [{
campaignType: 1, name: 'Orthopedic'
}] },
{ campaignId: 333, campaignCategory: 'Cardiology', result: [{
campaignType: 3, name: 'Cardiology'
},
{
campaignType: 1, name: 'Cardiology 123'
}]} ];
var res = data.filter(campaign => campaign.result.some(type => type.campaignType === 3));
res = res.map(campaign => {
campaign.result = campaign.result.filter(type => type.campaignType ===3);
return campaign;
});
console.log(res);
It seems to me you can get this result with a simple Array.reduce and Array.forEach like this:
let data = [{ "campaignId": 111, "campaignCategory": "Diabetes", "result": [{ "campaignType": 1, "name": "tes1" }, { "campaignType": 1, "name": "test22" }, { "campaignType": 3, "name": "test33" } ] }, { "campaignId": 222, "campaignCategory": "Orthopedic", "result": [{ "campaignType": 1, "name": "Orthopedic" }] }, { "campaignId": 333, "campaignCategory": "Cardiology", "result": [{ "campaignType": 3, "name": "Cardiology" }, { "campaignType": 1, "name": "Cardiology 123" } ] } ]
let result = data.reduce((r,{result,...rest}) => {
result.forEach(x => x.campaignType === 3 ? r.push({...rest, result:[x]}) : null)
return r
}, [])
console.log(result)

Search for all paths to the value in JavaScript object

I have a complex JavaScript object given below.
An example object:
var object= {
"name": "tfifkhul",
"id": "262761",
"children": [
{
"name": "rthrth",
"id": 0,
"children": [
{
"name": "test",
"id": "262762",
"children": []
}
]
},
{
"name": "rthsrth",
"id": 0,
"children": [
{
"name": "test",
"id": "262762",
"children": []
}
]
},
{
"name": "rthrthhrth",
"id": 0,
"children": [
{
"name": "test",
"id": "262762",
"children": [
{
"name": "rtjrtj",
"id": 0,
"children": [
{
"name": "fwefwefwef",
"id": "262768",
"children": []
}
]
},
{
"name": "hsrtjrtdjrtj",
"id": 0,
"children": [
{
"name": "we4yhesrhy",
"id": "262764",
"children": []
}
]
},
{
"name": "lol",
"id": "262763",
"children": [
{
"name": "fwefwefwef",
"id": "262768",
"children": [
{
"name": "87ok78",
"id": "262765",
"children": [
{
"name": "78o78",
"id": 0,
"children": [
{
"name": "we4yhesrhy",
"id": "262764",
"children": [
{
"name": "test1",
"id": 0,
"children": [
{
"name": "",
"id": "262766",
"children": []
}
]
},
{
"name": "test2",
"id": 0,
"children": [
{
"name": "",
"id": "262766",
"children": []
}
]
}
]
}
]
},
{
"name": "7o78o76o8",
"id": 0,
"children": [
{
"name": "",
"id": "262766",
"children": []
}
]
},
{
"name": "ko",
"id": 0,
"children": [
{
"name": "",
"id": "262767",
"children": []
}
]
}
]
}
]
}
]
}
]
}
]
}
]
};
I need to create a function to search for all matching values for key "id" with given value.
So far I have created one recursive function:
function searchOccurances(theObject, value,path) {
var result = null;
if(theObject instanceof Array) {
for(var i = 0; i < theObject.length; i++) {
result = searchOccurances(theObject[i],value,path+","+i);
}
}
else
{
for(prop in theObject) {
if(prop == 'id') {
if(theObject[prop] == value) {
keyOccurances.push(path);
}
}
if((theObject[prop] instanceof Array) || (theObject[prop] instanceof Object))
{
if((theObject[prop].length!=undefined)&&(theObject[prop].length!=0))
{
result = searchOccurances(theObject[prop],value,path+","+prop);
}
}
}
}
return result;
}
keyOccurances=[];
searchOccurances(object,262762,'');
console.log(keyOccurances);
//Output
[",children,0,children,0", ",children,1,children,0", ",children,2,children,0"] -- correct
keyOccurances=[];
searchOccurances(object,262768,'');
console.log(keyOccurances);
//Output
[",children,1,children,0,children,1,children,0", ",children,1,children,0,children,2,children,0"] --wrong
The function returns array of comma separated paths of matched value but doesn't seems to be getting right results. For the first call with value '262762' gives corrects path list but for value '262768' gives incorrect path list.
Kindly help.
I'd suggest to provide a better test object. Would you really have so many children with 'id = 0' in a real use case? Would you have 2 children with the same ID at all? That makes things pretty hard to debug.
Below is an example function that should work as expected.
function search(object, value) {
var res = [], searchPath;
(searchPath = function(children, path) {
var n, newPath;
for(n in children) {
if(typeof children[n].id !== 'undefined' && parseInt(children[n].id, 10) === value) {
res.push(path);
}
newPath = path.slice();
newPath.push(children[n].id);
searchPath(children[n].children, newPath);
}
})([ object ], []);
return res;
}
console.log(search(object, 262762));
console.log(search(object, 262768));
Output:
[["262761", 0], ["262761", 0], ["262761", 0]]
[["262761", 0, "262762", 0], ["262761", 0, "262762", "262763"]]
The above code is not (yet) bullet-proof but hopefully is it short enough to be easily understandable.
If I understand your questions correctly, you're looking for all paths where a specific id is present. I'd recommend not reinventing the wheel here and using an existing library. We use object-scan for most of our data processing now. It's powerful once you wrap your head around it. Here is how you'd answer your question
// const objectScan = require('object-scan');
const findKeys = (haystack, id) => objectScan(['**'], {
joined: true,
filterFn: ({ value }) => value.id === id
})(haystack);
const object = { name: 'tfifkhul', id: '262761', children: [{ name: 'rthrth', id: 0, children: [{ name: 'test', id: '262762', children: [] }] }, { name: 'rthsrth', id: 0, children: [{ name: 'test', id: '262762', children: [] }] }, { name: 'rthrthhrth', id: 0, children: [{ name: 'test', id: '262762', children: [{ name: 'rtjrtj', id: 0, children: [{ name: 'fwefwefwef', id: '262768', children: [] }] }, { name: 'hsrtjrtdjrtj', id: 0, children: [{ name: 'we4yhesrhy', id: '262764', children: [] }] }, { name: 'lol', id: '262763', children: [{ name: 'fwefwefwef', id: '262768', children: [{ name: '87ok78', id: '262765', children: [{ name: '78o78', id: 0, children: [{ name: 'we4yhesrhy', id: '262764', children: [{ name: 'test1', id: 0, children: [{ name: '', id: '262766', children: [] }] }, { name: 'test2', id: 0, children: [{ name: '', id: '262766', children: [] }] }] }] }, { name: '7o78o76o8', id: 0, children: [{ name: '', id: '262766', children: [] }] }, { name: 'ko', id: 0, children: [{ name: '', id: '262767', children: [] }] }] }] }] }] }] }] };
console.log(findKeys(object, '262762'));
/* =>
[ 'children[2].children[0]',
'children[1].children[0]',
'children[0].children[0]' ]
*/
console.log(findKeys(object, '262768'));
/* =>
[ 'children[2].children[0].children[2].children[0]',
'children[2].children[0].children[0].children[0]' ]
*/
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.8.0"></script>
Disclaimer: I'm the author of object-scan
Edit: The accepted answer didn't make much sense to me (based on the question), but here is how you could generate the same output
// const objectScan = require('object-scan');
const findIdPath = (haystack, id) => objectScan(['**'], {
reverse: false,
filterFn: ({ value, parents, context }) => {
if (value.id === id) {
context.push(parents.filter((p) => 'id' in p).map((p) => p.id).reverse());
}
}
})(haystack, []);
const object = { name: 'tfifkhul', id: '262761', children: [{ name: 'rthrth', id: 0, children: [{ name: 'test', id: '262762', children: [] }] }, { name: 'rthsrth', id: 0, children: [{ name: 'test', id: '262762', children: [] }] }, { name: 'rthrthhrth', id: 0, children: [{ name: 'test', id: '262762', children: [{ name: 'rtjrtj', id: 0, children: [{ name: 'fwefwefwef', id: '262768', children: [] }] }, { name: 'hsrtjrtdjrtj', id: 0, children: [{ name: 'we4yhesrhy', id: '262764', children: [] }] }, { name: 'lol', id: '262763', children: [{ name: 'fwefwefwef', id: '262768', children: [{ name: '87ok78', id: '262765', children: [{ name: '78o78', id: 0, children: [{ name: 'we4yhesrhy', id: '262764', children: [{ name: 'test1', id: 0, children: [{ name: '', id: '262766', children: [] }] }, { name: 'test2', id: 0, children: [{ name: '', id: '262766', children: [] }] }] }] }, { name: '7o78o76o8', id: 0, children: [{ name: '', id: '262766', children: [] }] }, { name: 'ko', id: 0, children: [{ name: '', id: '262767', children: [] }] }] }] }] }] }] }] };
console.log(findIdPath(object, '262762'));
// => [ [ '262761', 0 ], [ '262761', 0 ], [ '262761', 0 ] ]
console.log(findIdPath(object, '262768'));
// => [ [ '262761', 0, '262762', 0 ], [ '262761', 0, '262762', '262763' ] ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.8.0"></script>
Disclaimer: I'm the author of object-scan

Categories

Resources