push element in a array of object javascript - javascript

I have an array of objects with objects and children and children can have elements
let array = {
account: "account 1",
children: [
{
account: "1",
},
{
account: "2",
},
],
total: {
debit: 96,
credit:96,
},
},
{
account: "account 2",
children: [
{
account: "1",
},
],
total: {
debit: 45,
credit: 96,
},
}
]
The expected array is to push an object to each of the children here and the object will be the total object we have at the bottom.
Expected Result:
let resultArray = {
account: "account 1",
children: [
{
account: "1",
},
{
account: "2",
},
{
debit: 96,
credit:96,
},
],
total: {
debit: 96,
credit:96,
},
},
{
account: "account 2",
children: [
{
account: "1",
},
{
debit: 45,
credit: 96,
},
],
total: {
debit: 45,
credit: 96,
},
},
Any suggestions for the same?

var resultArray = array.map((data) => {
const newChildrenArray = [...data.children];
newChildrenArray.push({...data.total});
return { ...data, children: newChildrenArray };
});
Note:
Your array and resultArray are not valid.
They should be like:
let array = [obj1, obj2]
Hope this will solve your problem!

Related

Nested filtering of 2D array doesn't work as expected

I have a 2D array where the outer array contains objects, each of which contains another array of objects. Here is the data:
const companies = [{
companyId: 100,
companyName: "Company 1",
transactions: [
{ id: "10421", date: "09/19/2022", selected: true, },
{ id: "00467", date: "05/08/2022", selected: true, },
],
},
{
companyId: 200,
companyName: "Company 2",
transactions: [
{ id: "259A6", date: "01/11/2022", selected: false, },
{ id: "87K37", date: "04/14/2022", selected: false, },
],
},
];
I want to get the list of transactions that have their selected fields set to true. This is how I am filtering the data:
const selectedTransactions = companies.filter((c) =>
c.transactions.filter((t) => t.selected === true));
Instead of getting the transactions of only the first company, I'm getting the transactions of ALL companies, including the ones that are not selected. Am I making a mistake somewhere?
You could flat-map the overall companies; then internally filter and map the transaction IDs and dates along with the company ID.
const companies = [{
companyId: 100,
companyName: "Company 1",
transactions: [
{ id: "10421", date: "09/19/2022", selected: true },
{ id: "00467", date: "05/08/2022", selected: true },
],
}, {
companyId: 200,
companyName: "Company 2",
transactions: [
{ id: "259A6", date: "01/11/2022", selected: false },
{ id: "87K37", date: "04/14/2022", selected: false },
],
}];
const selected = companies
.flatMap(({ companyId, transactions }) => transactions
.filter(({ selected }) => selected)
.map(({ id: transactionId, date: transactionDate }) =>
({ companyId, transactionId, transactionDate })));
console.log(selected);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Result
[
{ "companyId": 100, "transactionId": "10421", "transactionDate": "09/19/2022" },
{ "companyId": 100, "transactionId": "00467", "transactionDate": "05/08/2022" }
]
If youre just looking for the transactions you could use map, though it does return a second empty array. Or just add a little to your filter function to get only the company with what youre looking for.
const companies = [{
companyId: 100,
companyName: "Company 1",
transactions: [
{ id: "10421", date: "09/19/2022", selected: true },
{ id: "00467", date: "05/08/2022", selected: true },
],
}, {
companyId: 200,
companyName: "Company 2",
transactions: [
{ id: "259A6", date: "01/11/2022", selected: false },
{ id: "87K37", date: "04/14/2022", selected: false },
],
}];
// USING MAP TO GET TRANSACTIONS
const st = companies.map(c => c.transactions.filter(t => t.selected === true))
console.log(st);
// USING FILTER TO GET COMPANY
const selectedTransactions = companies.filter(c => {
c.transactions = c.transactions.filter(t => t.selected === true);
if (c.transactions.length) return c;
});
console.log(selectedTransactions);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Result
1
[
[
{
"id": "10421",
"date": "09/19/2022",
"selected": true
},
{
"id": "00467",
"date": "05/08/2022",
"selected": true
}
],
[]
]
2
[
{
"companyId": 100,
"companyName": "Company 1",
"transactions": [
{
"id": "10421",
"date": "09/19/2022",
"selected": true
},
{
"id": "00467",
"date": "05/08/2022",
"selected": true
}
]
}
]

JS filtering an Array item through a value in a nested Array

I can't figure out how to properly use .filter() to find an object in an Array by searching for a value in its nested Array.
I have the following data:
const orders = [
{
id: 1,
items: [
{
itemId: "abc",
},
{
itemId: "def",
},
],
},
{
id: 2,
items: [
{
itemId: "jkl",
},
{
itemId: "mno",
},
],
},
{
id: 3,
items: [
{
itemId: "abc",
},
{
itemId: "xyz",
},
],
},
];
I have the needed itemId: "abc" which I need to use to find all the objects that have items that also have the Id of "abc", so that the result is this:
[
{
id: 1,
items: [
{
itemId: "abc",
},
{
itemId: "def",
},
],
},
{
id: 3,
items: [
{
itemId: "abc",
},
{
itemId: "xyz",
},
],
},
]
So far, I've tried the following:
orders &&
orders.filter((order) => {
return order.items.filter((item) => item.itemId === "abc");
});
But it doesn't seem to work. What am I missing here?
Chris G beat me to it in the comments but he is right, you need to use order.items.some in your inner function:
const orders = [{
id: 1,
items: [{
itemId: "abc",
},
{
itemId: "def",
},
],
},
{
id: 2,
items: [{
itemId: "jkl",
},
{
itemId: "mno",
},
],
},
{
id: 3,
items: [{
itemId: "abc",
},
{
itemId: "xyz",
},
],
},
]
var ans = orders.filter((order) => {
return order.items.some((item) => item.itemId === "abc");
});
console.log(ans)
const orders = [{
id: 1,
items: [{
itemId: "abc",
},
{
itemId: "def",
},
],
},
{
id: 2,
items: [{
itemId: "jkl",
},
{
itemId: "mno",
},
],
},
{
id: 3,
items: [{
itemId: "abc",
},
{
itemId: "xyz",
},
],
},
];
const result = orders.filter(order =>
order.items.find(item => item.itemId === 'abc') !== undefined
)
console.log(result);

Structuring an array the correct way with lodash groupBy

I have an object that looks like this:
{
data: [
{ id: "1", state: "accepted", estimate_date: "2019-12-17" },
{ id: "2", state: "rejected", estimate_date: "2019-12-17" },
{ id: "3", state: "open", estimate_date: "2019-12-17" },
{ id: "4", state: "open", estimate_date: "2019-12-18" },
{ id: "5", state: "rejected", estimate_date: "2019-12-18" },
{ id: "6", state: "accepted", estimate_date: "2019-12-18" },
]
}
When I use lodash groupBy on the object like this:
const key = 'data';
const groupedEstimates = groupBy(estimateData[key], 'estimate_date');
It returns:
[
[
"2019-12-17"
],
[
[ { id: "1", state: "accepted" } ],
[ { id: "2", state: "rejected" } ],
[ { id: "3", state: "open" } ]
]
],
[
[
"2019-12-18"
],
[
[ { id: "4", state: "open" } ],
[ { id: "5", state: "rejected" } ],
[ { id: "6", state: "accepted" } ]
]
]
But now I'm trying to achieve something like this:
[
{
date: "2019-12-17",
items: [
{ id: "1", state: "accepted" },
{ id: "2", state: "rejected" },
{ id: "3", state: "open" },
]
},
{
date: "2019-12-18",
items: [
{ id: "4", state: "open" },
{ id: "5", state: "rejected" },
{ id: "6", state: "accepted" },
]
}
]
Except I don't know how to achieve that using lodash. It doesn't have to use lodash but I only used that at the start as it seemed an easy solution to my problem. Now that I'm trying to achieve a more sensible data structure I would like some insights on how to achieve it.
After grouping by the estimate_date property, iterate the groups object with _.map(). Generate the group's object by taking the key (2nd param) for the date property, and mapping the items to omit the estimate_date:
const estimateData = {"data":[{"id":"1","state":"accepted","estimate_date":"2019-12-17"},{"id":"2","state":"rejected","estimate_date":"2019-12-17"},{"id":"3","state":"open","estimate_date":"2019-12-17"},{"id":"4","state":"open","estimate_date":"2019-12-18"},{"id":"5","state":"rejected","estimate_date":"2019-12-18"},{"id":"6","state":"accepted","estimate_date":"2019-12-18"}]}
const groupedEstimates = _.map(
_.groupBy(estimateData.data, 'estimate_date'),
(items, date) => ({
date,
items: items.map(o => _.omit(o, 'estimate_date'))
})
)
console.log(groupedEstimates)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

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