How to reformat json as nested json by parent_id - javascript

Here is the Json array, Every object has is_parent and parent_id properties,
If and object has children objects then it's is_parent property is 1 and vice versa.
let list = [
{id: 4, name: 'dd', is_parent: 1, parent_id: 0},
/**/{id: 5, name: 'ee', is_parent: 0, parent_id: 4},
/**/{id: 6, name: 'ff', is_parent: 1, parent_id: 5},
/**//**/{id: 7, name: 'gg', is_parent: 0, parent_id: 6},
{id: 8, name: 'hh', is_parent: 1, parent_id: 0},
/**/{id: 9, name: 'ii', is_parent: 0, parent_id: 8},
{id: 10, name: 'jj', is_parent: 1, parent_id: 0},
/**/{id: 11, name: 'kk', is_parent: 1, parent_id: 10},
/**//**/{id: 12, name: 'll', is_parent: 1, parent_id: 11},
/**//**//**/{id: 13, name: 'mm', is_parent: 0, parent_id: 12},
],
I want to format above json array as below
let array = [
{
id: 4,
name: 'dd',
is_parent: 1,
parent_id: 0,
children: [
{id: 5, name: 'ee', is_parent: 0, parent_id: 4},
{
id: 6,
name: 'ff',
is_parent: 1,
parent_id: 5,
children: [
{id: 7, name: 'gg', is_parent: 0, parent_id: 6}
]
}
]
},
{
id: 8,
name: 'hh',
is_parent: 1,
parent_id: 0,
children: [
{id: 9, name: 'ii', is_parent: 0, parent_id: 8}
]
},
{
id: 10,
name: 'jj',
is_parent: 1,
parent_id: 0,
children: [
{
id: 11,
name: 'kk',
is_parent: 1,
parent_id: 10,
children: [
{
id: 12,
name: 'll',
is_parent: 1,
parent_id: 11,
children: [
{id: 13, name: 'mm', is_parent: 0, parent_id: 12}
]
}
]
}
]
},
]
I tried to do this by foreach loop inside another foreach loop but it didn't work

Try this.
let formattedJon = (data, root) => {
const t = {};
this.list.forEach(o => ((t[o.parent_id] ??= {}).children ??= []).push(Object.assign(t[o.id] ??= {}, o)));
return t[root].children;
},
data = {data: []},
result = Object.fromEntries(Object
.entries(data)
.map(([k, v]) => [k, getTree(v, '0')])
);
console.log(result);
i found the answer from Build tree array from flat array in javascript

'use strict';
const createDataTree = dataset => {
const hashTable = Object.create(null);
dataset.forEach(aData => hashTable[aData.id] = {...aData, children: []});
const dataTree = [];
dataset.forEach(aData => {
if(aData.parent_id) {
hashTable[aData.parent_id].children.push(hashTable[aData.id]);
}
else {
dataTree.push(hashTable[aData.id]);
}
});
console.log(JSON.stringify(dataTree, null ,4))
return dataTree;
};
const list = [
{id: 4, name: 'dd', is_parent: 1, parent_id: 0},
/**/{id: 5, name: 'ee', is_parent: 0, parent_id: 4},
/**/{id: 6, name: 'ff', is_parent: 1, parent_id: 5},
/**//**/{id: 7, name: 'gg', is_parent: 0, parent_id: 6},
{id: 8, name: 'hh', is_parent: 1, parent_id: 0},
/**/{id: 9, name: 'ii', is_parent: 0, parent_id: 8},
{id: 10, name: 'jj', is_parent: 1, parent_id: 0},
/**/{id: 11, name: 'kk', is_parent: 1, parent_id: 10},
/**//**/{id: 12, name: 'll', is_parent: 1, parent_id: 11},
/**//**//**/{id: 13, name: 'mm', is_parent: 0, parent_id: 12},
];
createDataTree(list);
I have modifed the code and taken example from here . This is really good example and works like a charm

Related

filtering array of objects in react not working

I have an array of objects like below:
0: {Id: 1, name: 'xyz', pqID: 10, pqType: null}
1: {Id: 2, name: 'abc', pqID: 15, pqType: null}
2: {Id: 3, name: 'wer', pqID: 16, pqType: null}
3: {Id: 4, name: 'uyt', pqID: 18, pqType: null}
4: {Id: 5, name: 'qwe', pqID: 22, pqType: null}
5: {Id: 6, name: 'ert', pqID: 25, pqType: null}
I want objects of pqID and 10 and 15. Below is what I am trying which is giving empty array:
const newUsers = arr.filter(
(user) => user.pqID == 10 && user.pqID == 15
);
console.log(newUsers);
You could try that, with full array function syntax:
const newUsers = arr.filter(
(user) => {return [10, 15].includes(user.pqID)}
);
Or the minified version, without parentheses and curly brackets:
const newUsers = arr.filter(user => [10, 15].includes(user.pqID));
Note the || operator
var arr =
[{Id: 1, name: 'xyz', pqID: 10, pqType: null},
{Id: 2, name: 'abc', pqID: 15, pqType: null},
{Id: 3, name: 'wer', pqID: 16, pqType: null},
{Id: 4, name: 'uyt', pqID: 18, pqType: null},
{Id: 5, name: 'qwe', pqID: 22, pqType: null},
{Id: 6, name: 'ert', pqID: 25, pqType: null}]
const newUsers = arr.filter(
(user) =>
user.pqID == 10 || user.pqID == 15 // note ||
);
console.log(newUsers)

Combine two array into one while getting the sum of instances in second array

I have two arrays. The first array is this:
arrayOne = [
{id: 1, type: 'Animal', legs: 4},
{id: 2, type: 'Animal', legs: 2},
{id: 3, type: 'Animal', legs: 8},
{id: 4, type: 'Plant', legs: 0},
]
This is the second array:
arrayTwo = [
{typeId: 1, processing: 2},
{typeId: 1, processing: 3},
{typeId: 1, approved: 3},
{typeId: 1, approved: 2},
{typeId: 1, disapproved: 3},
{typeId: 1, disapproved: 2},
{typeId: 2, approved: 2},
{typeId: 2, disapproved: 1},
{typeId: 2, disapproved: 1},
{typeId: 3, approved: 2},
{typeId: 4, disapproved: 3},
]
If id of arrayOne is equal to typeId of arrayTwo, then append arrayTwo into arrayOne and sum up the number of processing, approved and disapproved. This is my desiredArray:
desiredArray = [
{id: 1, type: 'Animal', legs: 4, processing: 5, approved: 5, disapproved: 5},
{id: 2, type: 'Animal', legs: 2, approved: 2, disapproved: 2},
{id: 3, type: 'Animal', legs: 8, approved: 2},
{id: 4, type: 'Plant', legs: 0, disapproved: 3},
]
You can first reduce the second array and then map it to the first one:
const arrayOne = [{id: 1, type: 'Animal', legs: 4},{id: 2, type: 'Animal', legs: 2},{id: 3, type: 'Animal', legs: 8},{id: 4, type: 'Plant', legs: 0},];
const arrayTwo = [{typeId: 1, processing: 2},{typeId: 1, processing: 3},{typeId: 1, approved: 3},{typeId: 1, approved: 2},{typeId: 1, disapproved: 3},{typeId: 1, disapproved: 2},{typeId: 2, approved: 2},{typeId: 2, disapproved: 1},{typeId: 2, disapproved: 1},{typeId: 3, approved: 2},{typeId: 4, disapproved: 3},];
const reduced = arrayTwo.reduce((a,{typeId, ...rest})=>{
a[typeId] ??= {};
Object.entries(rest).forEach(([k,v])=>{
a[typeId][k] ??= 0;
a[typeId][k]+=v;
});
return a;
},{});
const result = arrayOne.map(o=>({...o, ...reduced[o.id]}));
console.log(result);
Let me code it for u.
arrayOne = [{
id: 1,
type: 'Animal',
legs: 4
},
{
id: 2,
type: 'Animal',
legs: 2
},
{
id: 3,
type: 'Animal',
legs: 8
},
{
id: 4,
type: 'Plant',
legs: 0
},
]
arrayTwo = [{
typeId: 1,
processing: 2
},
{
typeId: 1,
processing: 3
},
{
typeId: 1,
approved: 3
},
{
typeId: 1,
approved: 2
},
{
typeId: 1,
disapproved: 3
},
{
typeId: 1,
disapproved: 2
},
{
typeId: 2,
approved: 2
},
{
typeId: 2,
disapproved: 1
},
{
typeId: 2,
disapproved: 1
},
{
typeId: 3,
approved: 2
},
{
typeId: 4,
disapproved: 3
},
]
for (let x in arrayOne) {
for (let y of arrayTwo) {
if(arrayOne[x].id == y.typeId){
arrayOne[x] = {...arrayOne[x], ...y};
}
}
}
console.log(arrayOne)

how to map properties of two object arrays with different lengths in JavaScript

Being a newbie I have found this problem that I don't know to solve.
Given 2 arrays of different lengths I want to map the value of key total of arr2 over the value of key total of arr1 function of value of key grpId of arr1, as follow:
arr1 = [{id: 1, grpId: 'x', total: null},
{id: 2, grpId: 'x', total: null},
{id: 3, grpId: 'x', total: null},
{id: 4, grpId: 'y', total: null},
{id: 5, grpId: 'y', total: null}];
arr2 = [{id: 1, grpId: 'x', total: 3},
{id: 2, grpId: 'y', total: 2}];
I need the result as below:
arr1 = [{id: 1, grpId: 'x', total: 3},
{id: 2, grpId: 'x', total: 3},
{id: 3, grpId: 'x', total: 3},
{id: 4, grpId: 'y', total: 2},
{id: 5, grpId: 'y', total: 2}];
Try this:
const arr1 = [{id: 1, grpId: 'x', total: null},
{id: 2, grpId: 'x', total: null},
{id: 3, grpId: 'x', total: null},
{id: 4, grpId: 'y', total: null},
{id: 5, grpId: 'y', total: null}];
const arr2 = [{id: 1, grpId: 'x', total: 3},
{id: 2, grpId: 'y', total: 2}];
const output = arr1.map(entry => ({
...entry,
total: arr2.find(a2 => a2.grpId === entry.grpId).total
}));
console.log(output);
Should see the output in your console window. (Developer tools of your browser).
Use Array.map() to loop through arr1, and inside that loop through arr2 and assign the total values:
let arr1=[{id:1,grpId:"x",total:null},{id:2,grpId:"x",total:null},{id:3,grpId:"x",total:null},{id:4,grpId:"y",total:null},{id:5,grpId:"y",total:null}],arr2=[{id:1,grpId:"x",total:3},{id:2,grpId:"y",total:2}];
let res = arr1.map(el1 => {
arr2.forEach(el2 => {
if(el2.grpId == el1.grpId){
el1.total = el2.total
}
})
return el1
})
console.log(res)

Is there any lodash function to achieve this?

I have an array
var a = [
{id: 1, item: 3},
{id: 1, item: 4},
{id: 1, item: 5},
{id: 2, item: 6},
{id: 2, item: 7},
{id: 3, item: 8}
]
I need output like this:
[{id: 1, items: [3, 4, 5]}, {id: 2, items: [6,7]}, {id: 3, items: [8]}]
Here's a solution that first groups by id and then maps across the groupings to get the required collection:
let result = _(a)
.groupBy('id')
.map( (group ,id) => ({id: id, items: _.map(group, 'item')}))
.value()
It's pretty ugly, but then other answers are not pretty either
var a = [
{id: 1, item: 3},
{id: 1, item: 4},
{id: 1, item: 5},
{id: 2, item: 6},
{id: 2, item: 7},
{id: 3, item: 8}
];
var ret = _.chain(a)
.groupBy(elt => elt.id)
.mapValues(elt => _.reduce(elt, (acc, sub) => acc.concat(sub.item),[]))
.map((value, key) => ({id: key, items:value}))
.value();
console.log(ret);
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>

Ramda: get objects from array by comparing with each item in another array

I've an array like:
ids = [1,3,5];
and another array like:
items: [
{id: 1, name: 'a'},
{id: 2, name: 'b'},
{id: 3, name: 'c'},
{id: 4, name: 'd'},
{id: 5, name: 'e'},
{id: 6, name: 'f'}
];
What I want is another array like:
array = [{id: 1, name: 'a'}, {id: 3, name: 'c'}, {id: 5, name: 'e'}];
I can't get my head around it. so far i tried like:
console.log(R.filter(R.propEq('id', <donnow what shud be here>), items);
console.log( R.pick(ids)(items))
If you still want to do with Ramda:
const ids = [1,3,5];
const items = [
{id: 1, name: 'a'},
{id: 2, name: 'b'},
{id: 3, name: 'c'},
{id: 4, name: 'd'},
{id: 5, name: 'e'},
{id: 6, name: 'f'}
];
console.log(
R.filter(R.compose(R.flip(R.contains)(ids), R.prop('id')), items)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
You can use .filter and .indexOf. Note these are ECMA5 methods for Arrays, and will not work in IE8.
var ids = [1, 3, 5];
var items = [
{id: 1, name: 'a'},
{id: 2, name: 'b'},
{id: 3, name: 'c'},
{id: 4, name: 'd'},
{id: 5, name: 'e'},
{id: 6, name: 'f'}
];
var filtered = items.filter(function(obj) {
return ids.indexOf(obj.id) > -1;
});
console.log(filtered); // [{id: 1, name: 'a'}, {id: 3, name: 'c'}, {id: 5, name: 'e'}];
Or may be one liner without Ramda
items.filter(x=>ids.includes(x.id))
I suggest to use a hash table for faster lookup.
var ids = [1, 3, 5],
items = [{id: 1, name: 'a'}, {id: 2, name: 'b'}, {id: 3, name: 'c'}, {id: 4, name: 'd'}, {id: 5, name: 'e'}, {id: 6, name: 'f'} ],
filtered = items.filter(function(obj) {
return this[obj.id];
}, ids.reduce(function (r, a) {
r[a] = true;
return r;
}, Object.create(null)));
document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');

Categories

Resources