I have this structure of JS object:
const obj1 = {
"groups": [
{
"name": "test",
"type": "app"
},
{
"name": "test2",
"type": "app"
},
{
"name": "test1",
"type": "app2"
},
{
"name": "test3",
"type": "app2"
}
]
}
I need to finaly get this:
Result:
const obj1 = {
app: {groups: [{name: 'test'},{name: 'test2'}]},
app2: {groups: [{name: 'test1'},{name: 'test3'}]},
}
May be ES6+ aproach or older
This comes down to just iterating through obj1.groups building up a new output object:
const obj1 = {
"groups": [
{ "name": "test", "type": "app" },
{ "name": "test2", "type": "app" },
{ "name": "test1", "type": "app2" },
{ "name": "test3", "type": "app2" }
]
};
const out = {};
for (let group of obj1.groups) {
out[group.type] = out[group.type] || { groups: [] };
out[group.type].groups.push({ name: group.name });
}
console.log(out);
Alternatively, you could use Array.reduce() to wrap this up into a single expression:
const obj1 = {
"groups": [
{ "name": "test", "type": "app" },
{ "name": "test2", "type": "app" },
{ "name": "test1", "type": "app2" },
{ "name": "test3", "type": "app2" }
]
};
const out = obj1.groups.reduce((out, group) => {
out[group.type] = out[group.type] || { groups: [] };
out[group.type].groups.push({ name: group.name });
return out;
}, {});
console.log(out);
You can do it succinctly using Array.reduce():
const obj1 = {
"groups": [{ "name": "test", "type": "app" }, { "name": "test2", "type": "app" }, { "name": "test1", "type": "app2" }, { "name": "test3", "type": "app2" }]
};
const result = obj1.groups.reduce((obj, { name, type }) => {
return (obj[type].groups.push({ name }), obj);
}, { app: { groups: [] }, app2: { groups: [] } });
console.log(result);
Or using the spread operator:
const obj1 = {
"groups": [{ "name": "test", "type": "app" }, { "name": "test2", "type": "app" }, { "name": "test1", "type": "app2" }, { "name": "test3", "type": "app2" }]
};
const result = obj1.groups.reduce((o, { name, type }) =>
({ ...o, [type]: { groups: [...((o[type] || {}).groups || []), { name }] } }), {});
console.log(result);
Related
Input:
[{
"dimensions": [{
"name": "Size",
"value": "Size1"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "1"
}
],
"link": "link",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size2"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "2"
}
],
"link": "link1",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size1"
},
{
"name": "Color",
"value": "Color2"
},
{
"name": "Pattern",
"value": "1"
}
],
"link": "link",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size2"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "3"
}
],
"link": "link",
"title": "title"
}]
Expected Output:
{
"levels":3,
"level_1_name":"Size",
"level_2_name":"Color",
"level_3_name":"Pattern",
"data":[
{
"value":"Size1",
"data":[
{
"value":"Color1",
"data":[
{
"value":"1"
}
]
}, {
"value":"Color2",
"data":[
{
"value":"4"
}
]
}
]
}, {
"value":"Size2",
"data":[
{
"value":"Color1",
"data":[
{
"value":"3"
}
]
},
{
"value":"Color2",
"data":[
{
"value":"2"
}
]
}
]
}
]
}
I've tried something like that
for(index=0; index<data[0].dimensions.length - 1; index++) {
let temp = _(data).groupBy(function(o) {
return o.dimensions[index].value
})
let keys = Object.keys(temp)
addData(final, keys, temp)
}
obj["data"] = final
function addData(data, keys, temp) {
if (data && data.length) {
return data.forEach(function(data1){
console.log(data1)
return addData(data1, keys, temp)
})
} else {
let data_arr = []
if (Array.isArray(data)) {
keys.forEach(function(key) {
data.push({
value: key,
data: temp[key]
})
})
} else {
keys.forEach(function(key) {
let data_obj = {}
data_obj['value'] = key
data_obj['data'] = temp[key]
data_arr.push(data_obj)
})
data["data"] = data_arr
}
}
}
I've tried the logic to format as per the expected output. It works with level 2 input set, But the logic written doesn't work for level 3 input data set.
Also It would be helpful if you can suggest any algorithms to sort this problem out.
Thanks in advance!
Here is a fairly compact solution using reduce(). (I've edited the input to match your expected output.)
const source = [{
"dimensions": [{
"name": "Size",
"value": "Size1"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "1"
}
],
"link": "link",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size2"
},
{
"name": "Color",
"value": "Color2"
},
{
"name": "Pattern",
"value": "2"
}
],
"link": "link1",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size1"
},
{
"name": "Color",
"value": "Color2"
},
{
"name": "Pattern",
"value": "4"
}
],
"link": "link",
"title": "title"
},
{
"dimensions": [{
"name": "Size",
"value": "Size2"
},
{
"name": "Color",
"value": "Color1"
},
{
"name": "Pattern",
"value": "3"
}
],
"link": "link",
"title": "title"
}];
const output = source.reduce((acc, {dimensions: dims}) => {
const levels = dims.length;
// initialize top-level keys based on first object
if (!acc.hasOwnProperty('levels')) {
acc.levels = levels;
dims.forEach((level, i) => acc[`level_${i+1}_name`] = level.name);
acc.data = [];
}
// iterate over dimension objects and merge with accumulator
let parent = acc.data;
dims.forEach((o, i) => {
let lvlObj = parent.find(e => e.value === o.value);
if (!lvlObj) {
lvlObj = i < levels - 1 ?
{value: o.value, data: []} :
{value: o.value};
parent.push({...lvlObj});
}
parent = lvlObj.data;
});
return acc;
}, {});
console.log(output);
I have the following nested array of objects:
[
{
"info": [
{
"period": {
"start": "2020-01-01",
"end": "2020-01-31"
},
"info": [
{
"id": 036,
"name": "john",
},
{
"id": 037,
"name": "inna",
}
]
}
]
},
{
"info": [
{
"period": {
"start": "2020-01-01",
"end": "2020-01-31"
},
"info": [
{
"id": 045,
"name": "carl",
},
{
"id": 056,
"name": "tina",
}
]
}
]
}]
I want to extract all the values of the "name" property and put them in an array.
Output: ["john", "inna", "carl", "tina"].
Try with this code:
const userNames = [];
data.map(item => {
return item.info.map(registry => {
return registry.info.map(user => userNames.push(user.name));
})
})
Output: ["john", "inna", "carl", "tina"]
I am trying to traverse the data according to the show array and print the data to see if it is correct. To traverse the list array corresponding to the show array as follows
I want the effect as follows:
[
{
"name": "A",
"age": "10",
},
{
"name": "B",
"age": "20",
}
]
const data = [{
"code": "200",
"msg": "success",
"data": {
"list": [{
"name": "A",
"age": "10",
"logo": "aa.png",
"note": "aa"
}, {
"name": "B",
"age": "20",
"logo": "bb.png",
"note": "bb"
}],
"show": [
"name",
"age"
]
}
}]
function init() {
data.map(res => {
if (res.code == 200) {
console.log(res.data.list)
}
})
}
init();
By iterating show (rather than hard-coding name and age), this code would work also if you change the structure of your template:
const data = [{
"code": "200",
"msg": "success",
"data": {
"list": [{
"name": "A",
"age": "10",
"logo": "aa.png",
"note": "aa"
}, {
"name": "B",
"age": "20",
"logo": "bb.png",
"note": "bb"
}],
"show": [
"name",
"age"
]
}
}];
var ans = data[0].data.list.map(item => {
var curr = {};
data[0].data.show.forEach(prop => {
curr[prop] = item[prop];
});
return curr;
});
console.log(ans);
You can use reduce in a shorter way:
const data = [
{
code: "200",
msg: "success",
data: {
list: [
{
name: "A",
age: "10",
logo: "aa.png",
note: "aa"
},
{
name: "B",
age: "20",
logo: "bb.png",
note: "bb"
}
],
show: ["name", "age"]
}
}
];
console.log(data[0].data.list.map(x =>
data[0].data.show.reduce((p, c) => ((p[c] = x[c]), p), {})
));
const data = [{
"code": "200",
"msg": "success",
"data": {
"list": [{
"name": "A",
"age": "10",
"logo": "aa.png",
"note": "aa"
}, {
"name": "B",
"age": "20",
"logo": "bb.png",
"note": "bb"
}],
"show": [
"name",
"age"
]
}
}];
function init() {
data.map(res => {
if (res.code == 200) {
console.log(res.data.list.map(function(listValue) {
var ret = {};
res.data.show.forEach(function(idx) {
ret[idx] = listValue[idx]
});
return ret;
}));
}
})
}
init();
You can use .map on your data and return false if the code isn't 200, if it is 200, you can return a mapped version of your list array. You can map this array to a subset of each object in your list. The subset is defined by your show array, and so you can use .reduce() on this array to build your mapped object.
See example below:
const data = [{
"code": "200",
"msg": "success",
"data": {
"list": [{
"name": "A",
"age": "10",
"logo": "aa.png",
"note": "aa"
}, {
"name": "B",
"age": "20",
"logo": "bb.png",
"note": "bb"
}],
"show": [
"name",
"age"
]
}
}];
function init() {
return data.map(res => {
if (res.code == 200) {
return res.data.list.map((obj) => {
return res.data.show.reduce((acc, prop) => ({...acc, [prop]: obj[prop]}), {});
});
}
return false;
}).filter(Boolean); // filter out any `false` returns
}
console.log(init());
Alternatively, a better approach than mapping your original data would be to use .reduce(). This will create a one-dimensional array of results:
const data = [{
"code": "200",
"msg": "success",
"data": {
"list": [{
"name": "A",
"age": "10",
"logo": "aa.png",
"note": "aa"
}, {
"name": "B",
"age": "20",
"logo": "bb.png",
"note": "bb"
}],
"show": [
"name",
"age"
]
}
},
{
"code": "200",
"msg": "success",
"data": {
"list": [{
"name": "C",
"age": "30",
"logo": "aa.png",
"note": "aa"
}, {
"name": "D",
"age": "40",
"logo": "bb.png",
"note": "bb"
}],
"show": [
"name",
"age"
]
}
}];
function init() {
return data.reduce((acc, res) => {
if (res.code == 200) {
return [...acc, ...res.data.list.map((obj) => {
return res.data.show.reduce((acc, prop) => ({...acc, [prop]: obj[prop]}), {});
})];
}
return acc;
}, []);
}
console.log(init());
If you want to show only name and age as
[
{
"name": "A",
"age": "10",
},
{
"name": "B",
"age": "20",
}
]
Array.map can be used
and then you can write your code this way
const data = [
{
code: '200',
msg: 'success',
data: {
list: [
{
name: 'A',
age: '10',
logo: 'aa.png',
note: 'aa'
},
{
name: 'B',
age: '20',
logo: 'bb.png',
note: 'bb'
}
],
show: ['name', 'age']
}
}
]
function init() {
data.map(res => {
if (res.code == 200) {
console.log(
res.data.list.map(item => {
return {
name: item.name,
age: item.age
}
})
)
}
})
}
init()
Does this answer your question?
Can anyone help converting the following list of parent-child objects:
I have below array of objects, Need to convert it into parent child order. each 'Members' attribute in object may have 1 or n objects inside it. In 'Members' array the 1st object is parent of 2nd one and 2nd is parent of third object.
So in 1st Member
'Video' is parent of 'West' and 'West' is parent of 'India' and so on..
I have tried to loop through the elements one by one but could not reach the desired outcome.
Any help with the logic or code would be really helpful.
Input :
[
{
"Members": [
{
"Name": "Videos"
},
{
"Name": "West"
},
{
"Name": "India"
}
]
},
{
"Members": [
{
"Name": "Machinery"
},
{
"Name": "South"
},
{
"Name": "Australia"
}
]
},
{
"Members": [
{
"Name": "Electronics"
},
{
"Name": "Midwest"
},
{
"Name": "Arab"
}
]
},
{
"Members": [
{
"Name": "Machinery"
},
{
"Name": "West"
},
{
"Name": "India"
}
]
},
{
"Members": [
{
"Name": "Electronics"
},
{
"Name": "NorthEast"
},
{
"Name": "Japan"
}
]
},
{
"Members": [
{
"Name": "Videos"
},
{
"Name": "South"
},
{
"Name": "Australia"
}
]
},
{
"Members": [
{
"Name": "Videos"
},
{
"Name": "West"
},
{
"Name": "Japan"
}
]
}
]
Expected Output :
[
{
"name": "Videos",
"children": [
{
"name": "West",
"children": [
{
"name": "India",
"children": []
},
{
"name": "Japan",
"children": []
}
]
},
{
"name": "South",
"children": [
{
"name": "Australia",
"children": []
}
]
}
]
},
{
"name": "Machinery",
"children": [
{
"name": "South",
"children": [
{
"name": "Australia",
"children": []
}
]
},
{
"name": "West",
"children": [
{
"name": "India",
"children": []
}
]
}
]
},
{
"name": "Electronics",
"children": [
{
"name": "Midwest",
"children": [
{
"name": "Arab",
"children": []
}
]
},
{
"name": "NorthEast",
"children": [
{
"name": "Japan",
"children": []
}
]
}
]
}
]
```
Man this took too long. But it works with larger datasets. Note to OP, never use this data structure. Ever. It's horrible. I lost many braincells making this solution:
var arr = [
{Members: [{ Name: "Videos" }, { Name: "West" }, { Name: "India" }, {Name: 'Testing'}]},
{Members: [{ Name: "Machinery" }, { Name: "South" }, { Name: "Australia" }]},
{Members: [{ Name: "Electronics" }, { Name: "Midwest" }, { Name: "Arab" }]},
{Members: [{ Name: "Machinery" }, { Name: "West" }, { Name: "India" }]},
{Members: [{ Name: "Electronics" }, { Name: "NorthEast" }, { Name: "Japan" }]},
{Members: [{ Name: "Videos" }, { Name: "South" }, { Name: "Australia" }]},
{Members: [{ Name: "Videos" }, { Name: "West" }, { Name: "Japan" }]}
];
const addRelation = (obj, m, i) => ({...obj, parent: i === 0 ? null : m.slice(0, i).map(el => el.Name).join('.'), level: i, children: []})
const arrayToTree = (arr) => {
arr = arr.map(({ Members: m }) => m.map((obj, i) => addRelation(obj, m, i))).reduce((acc, arr) => {
arr.map(obj => acc.push(obj))
return acc
}, []).sort((a, b) => b.level - a.level)
var temp = [...arr].filter((o, index, self) =>
index === self.findIndex((t) => (
t.Name === o.Name && t.parent === o.parent
))
)
arr.forEach(() => {
if (temp[0].level === 0) return
var parentIndex = temp.findIndex(o => {
var str = temp[0].parent
var rest = str.substring(0, str.lastIndexOf("."));
var last = str.substring(str.lastIndexOf(".") + 1, str.length);
var parents = [rest, last]
return parents[0] !== ''
? o.Name === parents[1] && o.parent === parents[0]
: o.Name === temp[0].parent
})
const { Name, children } = temp[0]
temp[parentIndex].children.push({Name, children})
temp.shift()
})
return temp.map(({ Name, children }) => ({ Name, children }))
}
arr = arrayToTree(arr)
console.log(arr)
This might not be the best way to go about this and this only works for 3 levels.
var data = [
{
"Members": [
{
"Name": "Videos"
},
{
"Name": "West"
},
{
"Name": "India"
}
]
},
{
"Members": [
{
"Name": "Machinery"
},
{
"Name": "South"
},
{
"Name": "Australia"
}
]
},
{
"Members": [
{
"Name": "Electronics"
},
{
"Name": "Midwest"
},
{
"Name": "Arab"
}
]
},
{
"Members": [
{
"Name": "Machinery"
},
{
"Name": "West"
},
{
"Name": "India"
}
]
},
{
"Members": [
{
"Name": "Electronics"
},
{
"Name": "NorthEast"
},
{
"Name": "Japan"
}
]
},
{
"Members": [
{
"Name": "Videos"
},
{
"Name": "South"
},
{
"Name": "Australia"
}
]
},
{
"Members": [
{
"Name": "Videos"
},
{
"Name": "West"
},
{
"Name": "Japan"
}
]
}
];
function organize(dataBefore){
var dataAfter = [];
dataAfter.push({
name: dataBefore[0].Members[0].Name,
children: []
});
for(var i = 1; i < dataBefore.length; i++){
if(!doesExist(dataAfter, dataBefore[i].Members[0].Name)){
dataAfter.push({
name: dataBefore[i].Members[0].Name,
children: []
});
}
}
dataAfter[0].children.push({
name: dataBefore[0].Members[1].Name,
children: []
});
for(var i = 1; i < dataBefore.length; i++){
for(var j = 0; j < dataAfter.length; j++){
if(dataAfter[j].name == dataBefore[i].Members[0].Name){
if(!doesExist(dataAfter[j].children, dataBefore[i].Members[1].Name)){
dataAfter[j].children.push({
name: dataBefore[i].Members[1].Name,
children: []
});
}
}
}
}
dataAfter[0].children[0].children.push({
name: dataBefore[0].Members[2].Name,
children: []
});
for(var i = 1; i < dataBefore.length; i++){
for(var j = 0; j < dataAfter.length; j++){
if(dataAfter[j].name == dataBefore[i].Members[0].Name){
for(var k = 0; k < dataAfter[j].children.length; k++){
if(dataAfter[j].children[k].name == dataBefore[i].Members[1].Name){
if(!doesExist(dataAfter[j].children[k].children, dataBefore[i].Members[2].Name)){
dataAfter[j].children[k].children.push({
name: dataBefore[i].Members[2].Name,
children: []
});
}
}
}
}
}
}
return dataAfter;
}
function doesExist(checkThisData, searchValue){
for(var i = 0; i < checkThisData.length; i++){
if(searchValue == checkThisData[i].name){
return true;
}
}
return false;
}
console.log(organize(data));
I would advise to use map + reduce combination:
const data = [{
"Members": [{
"Name": "Videos"
},
{
"Name": "West"
},
{
"Name": "India"
}
]
},
{
"Members": [{
"Name": "Machinery"
},
{
"Name": "South"
},
{
"Name": "Australia"
}
]
},
{
"Members": [{
"Name": "Electronics"
},
{
"Name": "Midwest"
},
{
"Name": "Arab"
}
]
},
{
"Members": [{
"Name": "Machinery"
},
{
"Name": "West"
},
{
"Name": "India"
}
]
},
{
"Members": [{
"Name": "Electronics"
},
{
"Name": "NorthEast"
},
{
"Name": "Japan"
}
]
},
{
"Members": [{
"Name": "Videos"
},
{
"Name": "South"
},
{
"Name": "Australia"
}
]
},
{
"Members": [{
"Name": "Videos"
},
{
"Name": "West"
},
{
"Name": "Japan"
}
]
}
];
const ar = data.map((el, i) => {
let a = el['Members'].reduce((acc, member, index) => {
if (index === 0) {
acc[index] = {
name: member.Name,
children: []
};
} else {
debugger;
if (acc[0].children.length === 0) {
acc[0].children.push({
name: member.Name,
children: []
});
} else {
acc[0].children[0].children.push({
name: member.Name,
children: []
});
}
}
return acc;
}, []);
return a;
});
console.log(ar);
I have the json Like below, i want to get the unique child sub nodes for each main nodes
{
"name": "MENUS",
"value": "",
"children": [
{
"name": "MENU1",
"value": {},
"children": [
{
"name": "SubMenu1",
"value": {},
"children": [
{
"name": "SubMenu2",
"value": {},
"children": [
{
"name": "SubMenu3",
"value": {
"Pld": "1"
},
"children": []
}
]
}
]
}
]
},
{
"name": "MENU1",
"value": {},
"children": [
{
"name": "SubMenu1",
"value": {},
"children": [
{
"name": "SubMenu2",
"value": {},
"children": [
{
"name": "SubMenu4",
"value": {
"Pld": "1"
},
"children": []
}
]
}
]
}
]
}
]
}
I wanted the JSON like below format for each main nodes i want unique sub nodes means the subnode should not be a duplicate in the JSON.
{
"name": "MENUS",
"value": "",
"children": [
{
"name": "MENU1",
"value": {},
"children": [
{
"name": "SubMenu1",
"value": {},
"children": [
{
"name": "SubMenu2",
"value": {},
"children": [
{
"name": "SubMenu3",
"value": {
"Pld": "1"
},
"children": []
},
{
"name": "SubMenu4",
"value": {
"Pld": "1"
},
"children": []
}
]
}
]
}
]
}
]
}
Could you please anyone help me how to get the unique hierarchical tree JSON.
EDIT::Adding POJO classes for reference
This is how my java pojo looks like,
MenuTree.java
private String name;
private String value;
private Children[] children;
Children.java
private String name;
private Value value;
private Children[] children;
Value.java
private String Pld;
You could use an iterative and recursive approach by searching eachlevel for existing name and append the array with new objects if not found.
var object = { name: "MENUS", value: "", children: [{ name: "MENU1", value: {}, children: [{ name: "SubMenu1", value: {}, children: [{ name: "SubMenu2", value: {}, children: [{ name: "SubMenu3", value: { Pld: "1" }, children: [] }] }] }] }, { name: "MENU1", value: {}, children: [{ name: "SubMenu1", value: {}, children: [{ name: "SubMenu2", value: {}, children: [{ name: "SubMenu4", value: { Pld: "1" }, children: [] }] }] }] }] },
unique = [object].reduce(function iter(r, { name, value, children = [] }) {
var object = r.find(o => o.name === name);
if (!object) {
object = { name, value };
r.push(object);
}
children.reduce(iter, object.children = object.children || []);
return r;
}, []);
console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }