Related
I have an array of objects with Name, Key in all objects and ParentKey in some of the objects.
I want to group objects by unique 'Key' excluding those which have 'ParentKey'. The objects having ParentKey should be nested as reflected in required ans.
Initial Input :-
const arr = [
{
Name: 'Manage Leads',
Key: 'Manage Leads',
},
{
Name: 'Dashboard',
Key: 'Dashboard',
},
{
Name: 'Smart Views',
Key: 'Smart Views',
},
{
Name: 'Lead Details',
Key: 'Lead Details',
},
{
Name: 'Opportunity Details',
Key: 'Opportunity Details',
},
{
Name: 'Header',
Key: 'Header',
},
{
Name: 'Settings',
Key: 'Settings',
},
{
Name: 'Test 1',
Key: 'Test1Key',
},
{
Name: 'Test 1.1',
Key: 'Test1.1Key',
ParentKey: 'Test1',
},
{
Name: 'Test 1.2',
Key: 'Test1.2Key',
ParentKey: 'Test1',
},
{
Name: 'Test 1.1.1',
Key: 'Test1.1.1Key',
ParentKey: 'Test 1.1',
},
{
Name: 'Test 1.1.2',
Key: 'Test1.1.2Key',
ParentKey: 'Test 1.1',
},
{
Name: 'Test 1.2.1',
Key: 'Test1.2.1Key',
ParentKey: 'Test 1.2',
},
];
Required Output :-
[
{
groupName: 'Manage Leads',
actionsArr: [{ Name: 'Manage Leads', Key: 'Manage Leads' }],
},
{
groupName: 'Dashboard',
actionsArr: [{ Name: 'Dashboard', Key: 'Dashboard' }],
},
{
groupName: 'Smart Views',
actionsArr: [{ Name: 'Smart Views', Key: 'Smart Views' }],
},
{
groupName: 'Lead Details',
actionsArr: [{ Name: 'Lead Details', Key: 'Lead Details' }],
},
{
groupName: 'Opportunity Details',
actionsArr: [
{
Name: 'Opportunity Details',
Key: 'Opportunity Details',
},
],
},
{
groupName: 'Header',
actionsArr: [{ Name: 'Header', Key: 'Header' }],
},
{
groupName: 'Settings',
actionsArr: [{ Name: 'Settings', Key: 'Settings' }],
},
{
groupName: 'Test1Key',
actionsArr: [
{
Name: 'Test 1',
Key: 'Test1Key',
subActions: [
{
Name: 'Test 1.1',
Key: 'Test1.1',
ParentKey: 'Test1Key',
subActions: [
{
Name: 'Test 1.1.1',
Key: 'Test1.1.1Key',
ParentKey: 'Test 1.1',
},
{
Name: 'Test 1.1.2',
Key: 'Test1.1.2Key',
ParentKey: 'Test 1.1',
},
],
},
{
Name: 'Test 1.2',
Key: 'Test1.2',
ParentKey: 'Test1Key',
subActions: [
{
Name: 'Test 1.2.1',
Key: 'Test1.2.1Key',
ParentKey: 'Test 1.2',
},
],
},
],
},
],
},
];
I was able to group by unique Key with the follwoing code but i'm not able to nest the objects which have ParentKey.
const groupNames = [...new Set(actions.map((item) => item.GroupKey))];
const actionsList = groupNames.map((groupName) => {
const actionsArr = actions.filter((act) => act.GroupKey === groupName);
return { label: groupName, value: actionsArr }});
I found some inconsistencies between Key and ParentKey for the given data.
I have fixed the inconsistencies in the input data, and I would be using the same.
Here is the solution that worked for me.
const arr = [
{
Name: "Manage Leads",
Key: "Manage Leads",
},
{
Name: "Dashboard",
Key: "Dashboard",
},
{
Name: "Smart Views",
Key: "Smart Views",
},
{
Name: "Lead Details",
Key: "Lead Details",
},
{
Name: "Opportunity Details",
Key: "Opportunity Details",
},
{
Name: "Header",
Key: "Header",
},
{
Name: "Settings",
Key: "Settings",
},
{
Name: "Test 1",
Key: "Test1Key",
},
{
Name: "Test 1.1",
Key: "Test1.1Key",
ParentKey: "Test 1",
},
{
Name: "Test 1.2",
Key: "Test1.2Key",
ParentKey: "Test 1",
},
{
Name: "Test 1.1.1",
Key: "Test1.1.1Key",
ParentKey: "Test 1.1",
},
{
Name: "Test 1.1.2",
Key: "Test1.1.2Key",
ParentKey: "Test 1.1",
},
{
Name: "Test 1.2.1",
Key: "Test1.2.1Key",
ParentKey: "Test 1.2",
},
];
//recursively look for the child and append child to parent
const appendChild = (parent, arr) => {
for (let index = 0; index < arr.length; index++) {
const childElement = arr[index];
if (childElement.ParentKey == parent.Name) {
appendChild(childElement, arr);
if (parent.subActions) {
parent.subActions.push(childElement);
} else {
parent.subActions = [childElement];
}
//remove the child from that list and match the index
arr.splice(index, 1);
index--;
}
}
};
//convert data into a parent-child hierarchy
const convert = (arr) => {
for (const parent of arr) {
appendChild(parent, arr);
}
//filter out items which has been already added as child/subActions
return arr.filter((x) => !Boolean(x.ParentKey));
};
const groupBy = (items, callback) => {
const groupedData = items.reduce(
(acc, value, index) => (
(acc[callback(value, index, items)] ||= []).push(value), acc
),
{}
);
//convert grouped data as the required output
return Object.entries(groupedData).map(([key, value]) => ({
groupName: key,
actionsArr: value,
}));
};
const data = groupBy(convert(arr), (x) => x.Name);
console.log(JSON.stringify(data, null, 2));
Output:
[
{
"groupName": "Manage Leads",
"actionsArr": [
{
"Name": "Manage Leads",
"Key": "Manage Leads"
}
]
},
{
"groupName": "Dashboard",
"actionsArr": [
{
"Name": "Dashboard",
"Key": "Dashboard"
}
]
},
{
"groupName": "Smart Views",
"actionsArr": [
{
"Name": "Smart Views",
"Key": "Smart Views"
}
]
},
{
"groupName": "Lead Details",
"actionsArr": [
{
"Name": "Lead Details",
"Key": "Lead Details"
}
]
},
{
"groupName": "Opportunity Details",
"actionsArr": [
{
"Name": "Opportunity Details",
"Key": "Opportunity Details"
}
]
},
{
"groupName": "Header",
"actionsArr": [
{
"Name": "Header",
"Key": "Header"
}
]
},
{
"groupName": "Settings",
"actionsArr": [
{
"Name": "Settings",
"Key": "Settings"
}
]
},
{
"groupName": "Test 1",
"actionsArr": [
{
"Name": "Test 1",
"Key": "Test1Key",
"subActions": [
{
"Name": "Test 1.1",
"Key": "Test1.1Key",
"ParentKey": "Test 1",
"subActions": [
{
"Name": "Test 1.1.1",
"Key": "Test1.1.1Key",
"ParentKey": "Test 1.1"
},
{
"Name": "Test 1.1.2",
"Key": "Test1.1.2Key",
"ParentKey": "Test 1.1"
}
]
},
{
"Name": "Test 1.2",
"Key": "Test1.2Key",
"ParentKey": "Test 1",
"subActions": [
{
"Name": "Test 1.2.1",
"Key": "Test1.2.1Key",
"ParentKey": "Test 1.2"
}
]
}
]
}
]
}
]
Could you help me plese? I need to compare and calculate the percentage of the difference between the values and return an array. I need to compare arrays, get to objects with name and value, and count the percentage. Suppose for the first item in array {name: 'Name 1', value: 1945}, go into the second item to find there {name: 'Name 1', value: 699}. The percentage for 1945 will be 100, for 699 - 36. I'm confused about nesting((
//input data
const data = [
{
_id: "0090908",
groups: [
{
_id: "24424",
name: "Group 1",
group_type: "group_1",
items: [
{ name: "Name 1", value: 1945 },
{ name: "Name 2", value: 0 },
{ name: "Name 3", value: 39 },
],
},
{
_id: "23030",
name: "Group 2",
group_type: "group_2",
items: [
{ name: "Name 4", value: 67 },
{ name: "Name 5", value: 123 },
{ name: "Name 6", value: 13 },
],
},
]
},
{
_id: "00390395",
groups: [
{
_id: "837583",
name: "Group 1",
group_type: "group_1",
items: [
{ name: "Name 1", value: 699 },
{ name: "Name 2", value: 55},
{ name: "Name 3", value: 39 },
],
},
{
_id: "8989305",
name: "Group 2",
group_type: "group_2",
items: [
{ name: "Name 4", value: 998 },
{ name: "Name 5", value: 12 },
{ name: "Name 6", value: 485 },
],
},
]
}
];
//result data
const result = [
{
_id: "0090908",
groups: [
{
_id: "24424",
name: "Group 1",
group_type: "group_1",
items: [
{ name: "Name 1", value: 1945, percent: 100, best: true },
{ name: "Name 2", value: 0, percent: 0, best: false },
{ name: "Name 3", value: 39, percent: 100, best: true },
],
},
{
_id: "23030",
name: "Group 2",
group_type: "group_2",
items: [
{ name: "Name 4", value: 67, percent: 6, best: false },
{ name: "Name 5", value: 123, percent: 100, best: true },
{ name: "Name 6", value: 13, percent: 3, best: true },
],
},
]
},
{
_id: "00390395",
groups: [
{
_id: "837583",
name: "Group 1",
group_type: "group_1",
items: [
{ name: "Name 1", value: 699, percent: 36, best: false },
{ name: "Name 2", value: 55, percent: 100, best: true},
{ name: "Name 3", value: 39, percent: 100, best: true },
],
},
{
_id: "8989305",
name: "Group 2",
group_type: "group_2",
items: [
{ name: "Name 4", value: 998, percent: 100, best: true },
{ name: "Name 5", value: 12, percent: 9, best: false },
{ name: "Name 6", value: 485, percent: 100, best: true },
],
},
]
}
];
First you need to run through all elements, finding the largest values of each name. Then you run again, placing the percentages.
var best = {}; // Our database of higher values
function checkLargest(data) {
if (!data) return;
// If is iterable perform the function on each element
if (Symbol.iterator in Object(data)) for (var el of data) checkLargest(el);
if (data.name && data.value !== undefined)
if (!best[data.name] || best[data.name] < data.value)
best[data.name] = data.value;
checkLargest(data.groups); // If doesn't exist will return
checkLargest(data.items);
}
function placePercentages(data) {
if (!data) return;
if (Symbol.iterator in Object(data)) for (var el of data) placePercentages(el);
if (data.name && data.value !== undefined) {
var higher = best[data.name];
data.percent = Math.round(data.value / higher * 100);
data.best = (higher == data.value);
}
placePercentages(data.groups);
placePercentages(data.items);
}
const d = [
{
_id: "0090908",
groups: [
{
_id: "24424",
name: "Group 1",
group_type: "group_1",
items: [
{ name: "Name 1", value: 1945 },
{ name: "Name 2", value: 0 },
{ name: "Name 3", value: 39 },
],
},
{
_id: "23030",
name: "Group 2",
group_type: "group_2",
items: [
{ name: "Name 4", value: 67 },
{ name: "Name 5", value: 123 },
{ name: "Name 6", value: 13 },
],
},
]
},
{
_id: "00390395",
groups: [
{
_id: "837583",
name: "Group 1",
group_type: "group_1",
items: [
{ name: "Name 1", value: 699 },
{ name: "Name 2", value: 55},
{ name: "Name 3", value: 39 },
],
},
{
_id: "8989305",
name: "Group 2",
group_type: "group_2",
items: [
{ name: "Name 4", value: 998 },
{ name: "Name 5", value: 12 },
{ name: "Name 6", value: 485 },
],
},
]
}
];
checkLargest(d);
placePercentages(d);
console.log(d);
This is quite simple question, I got a Json like this:
const test = [
{
label: "Group 1",
options: [
{ label: "option 1", value: "value_1" },
{ label: "option 2", value: "value_2" }
]
},
{
label: "Group 1",
opions: [
{ label: "option 3", value: "value_3" },
{ label: "option 4", value: "value_4" }
]
},
{
label: "Group 2",
options: [
{ label: "option 5", value: "value_5" },
{ label: "option 6", value: "value_6" }
]
},
{
label: "Group 3",
options: [
{ label: "option 7", value: "value_7" },
{ label: "option 8", value: "value_8" }
]
},
{
label: "Group 3",
options: [
{ label: "option 9", value: "value_9" },
{ label: "option 10", value: "value_10" }
]
},
];
And I want to group them like this (by the Group label - the format is exactly as described below, I cannot add any other values as I'll use it in the react-select component as options)
const test = [
{
label: "Group 1",
options: [
{ label: "option 1", value: "value_1" },
{ label: "option 2", value: "value_2" },
{ label: "option 3", value: "value_3" },
{ label: "option 4", value: "value_4" }
]
},
{
label: "Group 2",
options: [
{ label: "option 5", value: "value_5" },
{ label: "option 6", value: "value_6" }
]
},
{
label: "Group 3",
options: [
{ label: "option 7", value: "value_7" },
{ label: "option 8", value: "value_8" },
{ label: "option 9", value: "value_9" },
{ label: "option 10", value: "value_10" }
]
},
];
How can I achieve that?
Thanks in advance
Please find the solution below for your problem statement.
const test = [{
label: "Group 1",
options: [{
label: "option 1",
value: "value_1"
},
{
label: "option 2",
value: "value_2"
}
]
},
{
label: "Group 1",
opions: [{
label: "option 3",
value: "value_3"
},
{
label: "option 4",
value: "value_4"
}
]
},
{
label: "Group 2",
options: [{
label: "option 5",
value: "value_5"
},
{
label: "option 6",
value: "value_6"
}
]
},
{
label: "Group 3",
options: [{
label: "option 7",
value: "value_7"
},
{
label: "option 8",
value: "value_8"
}
]
},
{
label: "Group 3",
options: [{
label: "option 9",
value: "value_9"
},
{
label: "option 10",
value: "value_10"
}
]
},
];
let temp = {};
test.forEach(t => {
const key = t.label;
if (temp[key]) {
const tempArray = temp[key].options.concat(t.options);
temp[key].options = tempArray;
} else {
temp[key] = {
label: key,
options: t.options
}
}
});
console.log(Object.values(temp));
I need a typescript function to recursively get the full path (parent hierarchy) of a given node by passing its value.
Let's say I have an array of objects like this:
items = [{
value: 2,
text: "Name 2",
children: [{
value: 7,
text: "Name 7",
children: [{
value: 10,
text: "Name 10",
children: []
},
{
value: 11,
text: "Name 11",
children: []
},
{
value: 12,
text: "Name 12",
children: [{
value: 13,
text: "Name 13",
children: [{
value: 14,
text: "Name 14",
children: []
},
{
value: 15,
text: "Name 15",
children: []
}
]
}]
}
]
}]
},
{
value: 16,
text: "Name 16",
children: [{
value: 17,
text: "Name 17",
children: [{
value: 18,
text: "Name 18",
children: []
},
{
value: 19,
text: "Name 19",
children: []
}
]
}]
}
];
Let's say I want to get the full path of node with value=19 by calling a function.
getPath(items, 19);
The expected result could be either returning only values of parent nodes
[16, 17, 19]
or array of objects as bellow:
[{
value: 16,
text: "Name 16"
},
{
value: 17,
text: "Name 17"
},
{
value: 19,
text: "Name 19"
}
]
Thanks,
Hope this help
const items = [{
value: 2,
text: "Name 2",
children: [{
value: 7,
text: "Name 7",
children: [{
value: 10,
text: "Name 10",
children: []
},
{
value: 11,
text: "Name 11",
children: []
},
{
value: 12,
text: "Name 12",
children: [{
value: 13,
text: "Name 13",
children: [{
value: 14,
text: "Name 14",
children: []
},
{
value: 15,
text: "Name 15",
children: []
}
]
}]
}
]
}]
},
{
value: 16,
text: "Name 16",
children: [{
value: 17,
text: "Name 17",
children: [{
value: 18,
text: "Name 18",
children: []
},
{
value: 19,
text: "Name 19",
children: []
}
]
}]
}
];
function getPath(items, val) {
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (item.value !== val) {
if (item.children) {
const path = getPath(item.children, val);
if (path) {
path.unshift(item.value);
return path;
}
}
} else {
return [item.value];
}
}
}
console.log(getPath(items, 19));
Here's the link for it
guys i have this json
var menu = [{
name: 'Computers',
children: [{
name: 'Notebook'
children: [{
name: 'Apple'
}, {
name: 'Windows'
}]
}, {
name: Tablets
children: [{
name: 'Apple'
}, {
name: 'Android'
}, {
name: 'Windows'
}]
}]
}, {
name: 'Phones',
children: [{
name: 'Android'
children: [{
name: 'Samsung'
}, {
name: 'Nokia'
}, {
name: 'Lenovo'
}]
}, {
name: 'Windows Phones'
children: [{
name: 'Microsoft'
}, {
name: 'Nokia'
}]
}]
}, {
name: 'Cameras',
children: [{
name: 'Digital'
children: [{
name: 'Nikon'
}, {
name: 'Fuji'
}]
}, {
name: 'DSLR'
children: [{
name: 'Canon'
}, {
name: 'Nikon'
}]
}]
}];
it says it is not valid json ... so how to make it valid json ??
any help would be appreciated ... thanks a lot
btw i am beginner so please help me
any suggestions ?? thanks again :)
You have some missing commas, where noted and a suposed to be a string without delimiters in your object literal.
var menu = [{
name: 'Computers',
children: [{
name: 'Notebook', // missing ,
children: [{
name: 'Apple'
}, {
name: 'Windows'
}]
}, {
name: 'Tablets', // missing string delimiter and comma
children: [{
name: 'Apple'
}, {
name: 'Android'
}, {
name: 'Windows'
}]
}]
}, {
name: 'Phones',
children: [{
name: 'Android', // missing ,
children: [{
name: 'Samsung'
}, {
name: 'Nokia'
}, {
name: 'Lenovo'
}]
}, {
name: 'Windows Phones', // missing ,
children: [{
name: 'Microsoft'
}, {
name: 'Nokia'
}]
}]
}, {
name: 'Cameras',
children: [{
name: 'Digital', // missing ,
children: [{
name: 'Nikon'
}, {
name: 'Fuji'
}]
}, {
name: 'DSLR', // missing ,
children: [{
name: 'Canon'
}, {
name: 'Nikon'
}]
}]
}];
console.log(menu);
.as-console-wrapper { max-height: 100% !important; top: 0; }
There are two problems
After name property values, comma is missing (at various places)
Tablets is not in quotes
Correct syntax would be.
var menu = [{
name: 'Computers',
children: [{
name: 'Notebook',
children: [{
name: 'Apple'
}, {
name: 'Windows'
}]
}, {
name: 'Tablets',
children: [{
name: 'Apple'
}, {
name: 'Android'
}, {
name: 'Windows'
}]
}]
}, {
name: 'Phones',
children: [{
name: 'Android',
children: [{
name: 'Samsung'
}, {
name: 'Nokia'
}, {
name: 'Lenovo'
}]
}, {
name: 'Windows Phones',
children: [{
name: 'Microsoft'
}, {
name: 'Nokia'
}]
}]
}, {
name: 'Cameras',
children: [{
name: 'Digital',
children: [{
name: 'Nikon'
}, {
name: 'Fuji'
}]
}, {
name: 'DSLR',
children: [{
name: 'Canon'
}, {
name: 'Nikon'
}]
}]
}];
You can copy your code is chrome's console to see where the error is.
you need to put double quotes on key an value like this "key" : "value"
[{
"name": "Computers",
"children": [{
"name": "Notebook",
"children": [{
"name": "Apple"
}, {
"name": "Windows"
}]
}, {
"name": "Tablets",
"children": [{
"name": "Apple"
}, {
"name": "Android"
}, {
"name": "Windows"
}]
}]
}]
And after name property values, comma is missing (at various places)
key and value should be wrapped by double quotes
copy paste the code validate here https://jsonformatter.curiousconcept.com/
[
{
"name":"Computers",
"children":[
{
"name":"Notebook",
"children":[
{
"name":"Apple"
},
{
"name":"Windows"
}
]
},
{
"name":"Tablets",
"children":[
{
"name":"Apple"
},
{
"name":"Android"
},
{
"name":"Windows"
}
]
}
]
},
{
"name":"Phones",
"children":[
{
"name":"Android",
"children":[
{
"name":"Samsung"
},
{
"name":"Nokia"
},
{
"name":"Lenovo"
}
]
},
{
"name":"Windows Phones",
"children":[
{
"name":"Microsoft"
},
{
"name":"Nokia"
}
]
}
]
},
{
"name":"Cameras",
"children":[
{
"name":"Digital",
"children":[
{
"name":"Nikon"
},
{
"name":"Fuji"
}
]
},
{
"name":"DSLR",
"children":[
{
"name":"Canon"
},
{
"name":"Nikon"
}
]
}
]
}
]