Iterate through array of objects and obtain a new array of object - javascript

I have below array of objects with each object having a projects attribute which further has its array of objects.
const data = [
{
"title": "Release",
"projects": [
{
"name": "Server",
"result": {
"success": 0,
"failure": 100
},
}
]
},
{
"title": "Payments",
"projects": [
{
"name": "Platform1",
"result": {
"success": 100,
"failure": 0
}
},
{
"name": "Platform2",
"result": {
"success": 50,
"failure": 50,
}
}
]
}
]
I wanted to iterate through it and get the result as follows. name is nothing but concatenation of title and name from above data.
const result = [
{
name: 'Release-Server',
success: 0,
failure: 100,
},
{
name: 'Payments-Platform1',
success: 100,
failure: 0,
},
{
name: 'Payments-Platform2',
success: 50,
failure: 5,
},
];
I have tried below ways but not able to figure out how to get exactly the result as shown above. can someone pls help on this.
data.forEach(prj => {
prj.projects.forEach((project) => {
// unable to get how to push these details into a new array of object
})
});

You can do the following (Make sure you add checks for null/undefined references)
const data = [{
"title": "Release",
"projects": [{
"name": "Server",
"result": {
"success": 0,
"failure": 100
},
}]
},
{
"title": "Payments",
"projects": [{
"name": "Platform1",
"result": {
"success": 100,
"failure": 0
}
},
{
"name": "Platform2",
"result": {
"success": 50,
"failure": 50,
}
}
]
}
];
const result = data.flatMap(item =>
item.projects.map(project => ({
name: `${item.title}-${project.name}`,
success: project.result.success,
failure: project.result.failure
})));
console.log(result);

You should use flatMap first because you have will change the number of elements (you start with 2, you end with 3) and inside a simple map to convert 1:1 each project into your final object.
Working Demo
const data = [{
"title": "Release",
"projects": [{
"name": "Server",
"result": {
"success": 0,
"failure": 100
},
}]
},
{
"title": "Payments",
"projects": [{
"name": "Platform1",
"result": {
"success": 100,
"failure": 0
}
},
{
"name": "Platform2",
"result": {
"success": 50,
"failure": 50,
}
}
]
}
];
var groupedData = data.flatMap((el) =>
el.projects.map((proj) => ({
name: el.title + "-" + proj.name,
success: proj.result.success,
failure: proj.result.failure,
}))
);
console.log(groupedData);

Related

Creating array of objects based on another array of objects

Trying creating array of objects based on another array of objects. Decided to use flatmap and then reduce, but the problem is when I have more than one object in result array - I can not collected several statuses in one object. Have added what i tried and what is result I am trying to achieve.
What I have
const data = [
{
"timestamp": "2021-08-31T15:29:18Z",
"result": [
{
"label": "Not Covered",
"value": 132
}
]
},
{
"timestamp": "2021-09-30T15:29:18Z",
"result": [
{
"label": "Not Covered",
"value": 135
}
]
},
{
"timestamp": "2021-10-31T16:29:18Z",
"result": [
{
"label": "Not Covered",
"value": 135
}
]
}
]
What I need to get
[
{
"Not Covered":132,
"Active":0,
"Expiring Soon":0,
"timestamp": "2021-08-31T15:29:18Z"
},
{
"Not Covered":135,
"Active":0,
"Expiring Soon":0,
"timestamp": "2021-09-30T15:29:18Z"
},
{
"Not Covered":135,
"Active":0,
"Expiring Soon":0,
"timestamp": "2021-10-31T16:29:18Z"
}
]
What I am doing
let flattenedResult = data.flatMap(({result,...r}) => result.map(o => ({ ...o,...r})));
const chartData = flattenedResult.reduce((acc, item) => {
const {timestamp, value,label} = item;
acc.push({timestamp, "Not Covered":"Not Covered"===label?value:0,"Active":"Active"===label?value:0,"Expiring Soon":"Expiring Soon"===label?value:0});
return acc;
}, []);
What i am getting:
[
{
"timestamp": "2021-08-31T15:29:18Z",
"Not Covered": 132,
"Active": 0,
"Expiring Soon": 0
},
{
"timestamp": "2021-09-30T15:29:18Z",
"Not Covered": 135,
"Active": 0,
"Expiring Soon": 0
},
{
"timestamp": "2021-10-31T16:29:18Z",
"Not Covered": 135,
"Active": 0,
"Expiring Soon": 0
}
]
You haven't explained how to get the values "Active" and "Expiring soon", but I'm sure something like that should help
const data = [
{
"timestamp": "2021-08-31T15:29:18Z",
"result": [
{
"label": "Expiring Soon",
"value": 57
},
{
"label": "Not Covered",
"value": 132
},
{
"label": "Active",
"value": 42
}
]
},
{
"timestamp": "2021-09-30T15:29:18Z",
"result": [
{
"label": "Not Covered",
"value": 135
}
]
},
{
"timestamp": "2021-10-31T16:29:18Z",
"result": [
{
"label": "Not Covered",
"value": 135
},
{
"label": "Active",
"value": 42
}
]
}
];
console.log(data.reduce((acc, {timestamp, result}) => {
const datum = result.reduce((acc, {label, value}) => {
acc[label] = value;
return acc;
}, {
timestamp,
'Not Covered': 0,
Active: 0,
'Expiring Soon': 0
});
return acc.concat(datum);
}, []));
What about something like this? You can then just put your "Active" and "ExpringSoon" according to your business logic.
const array = data.map(item => {
const results = {}
item.result.forEach(({ label, value }) => results[label] = value )
return {
Active: 0,
ExpiringSoon: 0,
timestamp: item.timestamp,
...results
}
})
Result
[
{
Active: 0,
ExpiringSoon: 0,
timestamp: '2021-08-31T15:29:18Z',
'Not Covered': 132
},
{
Active: 0,
ExpiringSoon: 0,
timestamp: '2021-09-30T15:29:18Z',
'Not Covered': 135
},
{
Active: 0,
ExpiringSoon: 0,
timestamp: '2021-10-31T16:29:18Z',
'Not Covered': 135
}
]

Javascript: How to loop through array of objects for post request for array property?

I have an array response and i need to pass post request data from that response. The response have nested array objects as well. So how to loop through those array objects into post api request key values ?
Response which i am getting is as below:
records = "data": [
{
"id": 1,
"title": "Black Panther",
"product_images": [
{
"id": 1,
"images": {
"id": 1,
"thumbnail_image": "/assets/1/image.jpg",
},
},
{
"id": 2,
"images": {
"id": 2,
"thumbnail_image": "/assets/2/image.jpg",
},
}
],
product_categories: [
{
"id": 1,
"categories": {
"id": 3,
"category_name": "Outdoor Sports"
}
}
]
}
]
Now i need to pass that product_images array object's images.thumbnail_image property into the post request key value.
records.map((element) => {
let data;
data = {
"id": element.id,
"name": element.title,
"image_files":
[
{
"url": "" // need to pass thumbnail_image value over here.
}
],
"product_category": {
"category_id": [1,2] // need to pass product_categories[i].categories.id value over here.
}
}
})
axios post API request is as below:
axios({
method: 'post',
url: 'api_url',
data: {
"products": data,
}
}).then((response) => {
console.log(response);
}).catch((error) => {
console.log(error)
});
P.S: I have tried to manage this issue with loop through into the image_files array as below but that is working.
"image_files": [
element.product_images.map((ele) => {
{
"url": ele.images.thumbnail_image
}
})
]
::Updated::
I also need to manage that category property into the post api request. I have tried like this way but it pass the [null] value
"category_id": lists.campaign_product_categories.map((element) => {
let arr = []
arr.push(element.categories.id)
}),
You can use a nested map statement with destructuring to achieve this.
let records = [ { "id": 1, "title": "Black Panther", "product_images": [ { "id": 1, "images": { "id": 1, "thumbnail_image": "/assets/1/image.jpg", }, }, { "id": 2, "images": { "id": 2, "thumbnail_image": "/assets/2/image.jpg", }, } ] } ];
let data = records.map(({id, title:name, product_images}) => (
{
id, name,
"image_files": product_images.map(({images:{thumbnail_image: url}})=>({
url
}))
}
));
console.log(data);
You can just map the sub array for each array element like so:
const records = [
{
id: 1,
title: "Black Panther",
product_images: [
{
id: 1,
images: {
id: 1,
thumbnail_image: "/assets/1/image.jpg",
},
},
{
id: 2,
images: {
id: 2,
thumbnail_image: "/assets/2/image.jpg",
},
},
],
},
];
const mapped = records.map((element) => ({
id: element.id,
name: element.title,
image_files: element.product_images.map((i) => ({
url: i.images.thumbnail_image,
})),
}));
console.log(mapped);
You need to run a map on the product images inner array to create the URL array
let apiResponses = records.data.map((dataElement) => {
let urls = dataElement.product_images.map((product_image) => {
return {"url": product_image.images.thumbnail_image}
})
return {
"id": dataElement.id,
"name": dataElement.title,
"image_files":
urls,
}
})
console.log(apiResponses[0])
Outputs
{
id: 1,
name: 'Black Panther',
image_files: [ { url: '/assets/1/image.jpg' }, { url: '/assets/2/image.jpg' } ]
}
Full code below
let records = {"data": [
{
"id": 1,
"title": "Black Panther",
"product_images": [
{
"id": 1,
"images": {
"id": 1,
"thumbnail_image": "/assets/1/image.jpg",
},
},
{
"id": 2,
"images": {
"id": 2,
"thumbnail_image": "/assets/2/image.jpg",
},
}
]
}
]}
let apiResponses = records.data.map((dataElement) => {
let urls = dataElement.product_images.map((product_image) => {
return {"url": product_image.images.thumbnail_image}
})
return {
"id": dataElement.id,
"name": dataElement.title,
"image_files":
urls,
}
})
console.log(apiResponses[0])
You forgot the return statement
records.map((element) => {
let data;
data = {
"id": element.id,
"name": element.title,
"image_files":
[
{
"url": "" // need to pass thumbnail_image value over here.
}
],
}
return data; // <------- this line
})

Filter data from Json to new Array which can be used in HighChartsJs

I am currently working with HighCharts JS. For data to be shown in HighCharts, I must have the final data as follows:
[
{
name: 'Performing',
data: [1941404, 1028717, 697370, 0, 0, 0]
},
{
name: 'Non performing',
data: [0, 0, 0, 1759908, 890857, 280235]
},
{
name: 'Substandard',
data: [0, 0, 863825, 0, 0, 0]
},
{
name: 'Written-off',
data: [0, 0, 0, 0, 0, 77146]
}
]
'Data' is an array of 6 objects which populate the xAxis of the chart.
However, I have the following data which is being supplied via MongoDb
const chartData = [
{
"_id": {
"data": "90 - 180",
"status": "Non Performing"
},
"value": 1759908
},
{
"_id": {
"data": "360",
"status": "Written-off"
},
"value": 77146
},
{
"_id": {
"data": "360",
"status": "Non Performing"
},
"value": 280235
},
{
"_id": {
"data": "30 - 90",
"status": "Substandard"
},
"value": 863825
},
{
"_id": {
"data": "30 - 90",
"status": "Performing"
},
"value": 697370
},
{
"_id": {
"data": "180 - 360",
"status": "Non Performing"
},
"value": 890857
},
{
"_id": {
"data": "0 - 30",
"status": "Performing"
},
"value": 1028717
},
{
"_id": {
"data": "0",
"status": "Performing"
},
"value": 1941404
}
]
I need to filter through the latter code so it ends up like the former code. It is very important that in the data array, we end up with 6 objects to make sure we populate the entire xAxis of Highcharts, hence we see lots of zeros, where no data was supplied.
I really hope this clears things up. Thank you to all those who have help. I apologise for being so vague from the offset.
QUICK NOTE The order of the data array is as follows: 0, 0-30, 30-90, 90-180, 180-360, 360
EDITTED
So this is the code I am using at the moment:
const data = this.chartData
let series
series = Object.values(data.reduce((acc, currVal) => {
acc[currVal._id.status] = acc[currVal._id.status] || {
name: currVal._id.status,
data: []
};
acc[currVal._id.status].data.push(currVal.totalBookValue) //push the year to data array after converting the same to a Number
return acc //return the accumulator
}, {}))
This kind of works, but its not populating the Data array with 6 elements.
Your problem can be solved via a bit of traversal using reduce() to reach object form and map() to return to array form (assuming the 0 to 360 list you posted is complete).
See below for a practical example.
// Input.
const input = [
{
"_id": {
"data": "90 - 180",
"status": "Non Performing"
},
"value": 1759908
},
{
"_id": {
"data": "360",
"status": "Written-off"
},
"value": 77146
},
{
"_id": {
"data": "360",
"status": "Non Performing"
},
"value": 280235
},
{
"_id": {
"data": "30 - 90",
"status": "Substandard"
},
"value": 863825
},
{
"_id": {
"data": "30 - 90",
"status": "Performing"
},
"value": 697370
},
{
"_id": {
"data": "180 - 360",
"status": "Non Performing"
},
"value": 890857
},
{
"_id": {
"data": "0 - 30",
"status": "Performing"
},
"value": 1028717
},
{
"_id": {
"data": "0",
"status": "Performing"
},
"value": 1941404
}
]
// Depth.
const depth = ['0', '0 - 30', '30 - 90', '90 - 180', '180 - 360', '360']
// Object Form.
const objectform = input.reduce((accumulator, x) => {
const { _id, value } = x // _id. Value.
let { data, status } = _id // Status.
status = status.toLowerCase() // Lower Case.
const point = {...accumulator[status], [data]: value} // Data.
return {...accumulator, [status]: point} // Update + Return Accumulator.
}, {})
// Output.
const output = Object.keys(objectform).map((key) => {
return {
name: key, // Name.
data: depth.map((frame) => objectform[key][frame] || 0) // Data.
}
})
// Log.
console.log(output)

How to change json structure to look like another json structure

I want to change my json structure, how can I do it?
im getting a json that looks like this:
body: {
"111111": {
"name": "exp1",
"status": 10000
},
"222222": {
"name": "exp2",
"status": 20000
},
"333333": {
"name": "exp3",
"status": 30000
}
}
but I need it in this structure:
body: {
bulks: [{
"id": "111111",
"name": "exp1",
"status": 100000
}, {
"id": "222222",
"name": "exp2",
"status": 200000
}, {
"id": "333333",
"name": "exp3",
"status": 300000
}]
}
Cause in my html I want to read it like this:
<div *ngIf="showingList">
<div class="list-bg" *ngFor="#bulk of listBulks | async">
ID: {{bulk.id}} name of item: {{bulk.name}}
</div>
</div>
Using Object#entries and Array#map with spread operator.
const data={body:{111111:{name:"exp1",status:1e4},222222:{name:"exp2",status:2e4},333333:{name:"exp3",status:3e4}}};
const res = {body:{bulk:Object
.entries(data.body)
.map(a=>({id: a[0], ...a[1]}))}};
console.log(res);
You can do it using reduce:
var body = {
"111111": {
"name": "exp1",
"status": 10000
},
"222222": {
"name": "exp2",
"status": 20000
},
"333333": {
"name": "exp3",
"status": 30000
}
}
var bodyArray = Object.keys(body).reduce(function(result, key) {
var item = body[key];
item.id = key;
result.push(item)
return result;
}, []);
As a simplest alternative to reduce, you could use the map() function.
const body = {
"111111": {
"name": "exp1",
"status": 10000
},
"222222": {
"name": "exp2",
"status": 20000
},
"333333": {
"name": "exp3",
"status": 30000
}
}
const newArray = Object.keys(body).map(function(key) {
const newObject = {
id: key,
...body[key]
};
return newObject;
});
console.log(newArray);

Compare two arrays of objects and filter results

Example:
const depositAddress = '2NBXPR5PRtW8xBRuDnWXBDXqHYpDPupWnhG';
DBarray1.forEach( (tx) => {
console.log(tx);
})
TXarray2.forEach( (sim) => {
console.log(sim);
});
DBarray1 = [
{
"_id": "575e2b7875a402111900ba8f",
"username": "aleluia#gmail.com",
"playerWallet": "2NFt8YfydBU5JD9U8Xq2ucbfUp2sP7BjUrh",
"User_Profile": {
"TXHash": [
"7fbe28f75412f19dfd123a08ce03c33c302aa13d1e68d38ab8cb4c7418777f8e"
]
}
},
{
"_id": "575e2946b909906a17ea65b9",
"username": "super#user.com",
"playerWallet": "2MzppxEX7xMidjhoJGczFDYsHk5TQwFkjS3",
"User_Profile": {
"TXHash": [
"cf948340a40d3302303dfb3710cfce37bb1cd156dcb6c74561fdc71c0a8fc30b",
"6219def49d2e8284a6031f4c7e05e21adf756d38904e6359bd7844ae14c75a50"
]
}
}
] // end console.log(DBarray1);
TXarray2 = [
{
"id": "cf948340a40d3302303dfb3710cfce37bb1cd156dcb6c74561fdc71c0a8fc30b",
"normalizedHash": "f62af1a61c7eb569c1a171ad23c70bc218bd7244c9c5c92cf7d98638314fbbc5",
"date": "2016-06-21T04:11:18.541Z",
"fee": 6280,
"inputs": [
{
"previousHash": "2660fb761354671912b0cea6427e9ee91a98a507e5f1408865a6058b566b508c",
"previousOutputIndex": 0
},
{
"previousHash": "ce3ef138c11ea4d1766cce52ccf5f1e91790bc03b56561b0eb669041bae4e1a3",
"previousOutputIndex": 0
}
],
"outputs": [
{
"vout": 0,
"account": "2N92kApgroS6CTVuTajtjWtpcAZpUiyQoDT",
"value": 861003
},
{
"vout": 1,
"account": "2NBXPR5PRtW8xBRuDnWXBDXqHYpDPupWnhG",
"value": 3100000,
"isMine": true,
"chain": 0,
"chainIndex": 0
}
],
"entries": [
{
"account": "2MzppxEX7xMidjhoJGczFDYsHk5TQwFkjS3",
"value": -3967283
},
{
"account": "2N92kApgroS6CTVuTajtjWtpcAZpUiyQoDT",
"value": 861003
},
{
"account": "2NBXPR5PRtW8xBRuDnWXBDXqHYpDPupWnhG",
"value": 3100000
}
],
"confirmations": 70,
"pending": false,
"instant": true,
"instantId": "5768be65427689eb06e597559c7e6cf0",
"blockhash": "00000000002d9fb51c7c3c1607fe062eff686aa6be657a59fee6c3044963897d",
"height": 872152
},
{
"id": "6219def49d2e8284a6031f4c7e05e21adf756d38904e6359bd7844ae14c75a50",
"normalizedHash": "179a4466fdfc5470e99e43aa177d43aa4f09e3a06760fd5bebffdda080d4407f",
"date": "2016-06-21T04:13:23.650Z",
"fee": 9096,
"inputs": [
{
"previousHash": "5d2879a79ea3d0dcb50049ef9ca46ef7e8d82caf2073a299a6cd0332add404c8",
"previousOutputIndex": 1
},
{
"previousHash": "d75288e69a3fc2edd534ddcd845af6a280a27af58013ae82828c8a8f813829c1",
"previousOutputIndex": 0
},
{
"previousHash": "eea4f9b274708b60c1b030203543a155857bc54aa11055ada04aceee706f96b9",
"previousOutputIndex": 0
}
],
"outputs": [
{
"vout": 0,
"account": "2NBXPR5PRtW8xBRuDnWXBDXqHYpDPupWnhG",
"value": 2000000,
"isMine": true,
"chain": 0,
"chainIndex": 0
},
{
"vout": 1,
"account": "2MzFTm5jnCDiAapjNnyVgZAJrXMKfQ74esV",
"value": 9859
}
],
"entries": [
{
"account": "2MzcwVFKF274bMNT5tNEDY7Ua7bAgvFUdu9",
"value": -35316
},
{
"account": "2MzFTm5jnCDiAapjNnyVgZAJrXMKfQ74esV",
"value": 9859
},
{
"account": "2MzppxEX7xMidjhoJGczFDYsHk5TQwFkjS3",
"value": -1983639
},
{
"account": "2NBXPR5PRtW8xBRuDnWXBDXqHYpDPupWnhG",
"value": 2000000
}
],
"confirmations": 70,
"pending": false,
"instant": true,
"instantId": "5768bee2b5bdf3f406e7db035aef016a",
"blockhash": "00000000002d9fb51c7c3c1607fe062eff686aa6be657a59fee6c3044963897d",
"height": 872152
},
{
"id": "7fbe28f75412f19dfd123a08ce03c33c302aa13d1e68d38ab8cb4c7418777f8e",
"normalizedHash": "b4f1974dccde5ea9dfb0abcd7d4a6f3f14995d9dd422aa7d2a9078229ff18ff4",
"date": "2016-06-21T03:39:25.034Z",
"fee": 3465,
"inputs": [
{
"previousHash": "97fbb6ed8646f7ce9ed10a4230a70348151d5b6b208ad068e3a1a3fddae2dc0e",
"previousOutputIndex": 2
}
],
"outputs": [
{
"vout": 0,
"account": "2NBXPR5PRtW8xBRuDnWXBDXqHYpDPupWnhG",
"value": 111200000,
"isMine": true,
"chain": 0,
"chainIndex": 0
},
{
"vout": 1,
"account": "2NFJnLrhsCDfG3ooQvGC169gnzBabtRgV2y",
"value": 244246993
}
],
"entries": [
{
"account": "2NCGUnwpNgaJbhMZKLJcBrWvZhWnai5PjVC",
"value": -355450458
},
{
"account": "2NFJnLrhsCDfG3ooQvGC169gnzBabtRgV2y",
"value": 244246993
},
{
"account": "2NBXPR5PRtW8xBRuDnWXBDXqHYpDPupWnhG",
"value": 111200000
}
],
"confirmations": 77,
"pending": false,
"instant": false,
"blockhash": "0000000000509dbc80cc3d86cdb10ce8e87ab7867c6775a9b00ca904fbe70da7",
"height": 872145
}
]// end console.log(TXarray2);
How can we check if TXarray2.id which is the transactions id, if it matches a payment made by the user inside DBarray1.User_Profile.TXHash for examplecf948340a40d3302303dfb3710cfce37bb1cd156dcb6c74561fdc71c0a8fc30b .
I want to know forEach TXarray2.id who made the payment . I tried to do this with promises and i will share some code when i get home but i'm sure it can be done with async for all users one by one and log who made a payment today to this wallet. I tried with array.find() method to check inside TXHash but failed, i don't fully grasp many prototype methods yet...
Hopefully someone already thinks this a walk on the park for him and found a better solution to validate this kind of stuff. I will accept any answer even with lodash, maping, anything. TY !!!
You iterate TXArray2 and do a lookup in DBarray1 for the transactionId.
I like to work with native array methods like map and filter, so I would use something like the following:
const result = TXarray2.map(tx => ({
transaction: tx,
user: DBarray1.filter(user => user.User_Profile.TXHash.indexOf(tx.id) > -1)[0]
}));
In this example result is an array where every element contains a transaction and the matching user.
If you already have all of the transaction and user data, could you do something like this?
// for each transaction in TXarray2
for (let { 'id': transactionId } of TXarray2) {
// check each entry in DBarray1
for (let { '_id': userId, 'User_Profile': { 'TXHash': transactions } } of DBarray1) {
if (transactions.includes(transactionId)) {
console.log(`${transactionId} was made by ${userId}`);
}
}
}
The best way here is to use Array.indexOf (or Array.findIndex if you want to use callbacks) which returns -1 if an entry is not in an array.
Here's the sync variant:
var paid = [];
TXArray2.forEach(function(transaction){
for(var i = 0; i < DBArray1.length; ++i){
if(DBArray1[i].User_Profile.TXHash.indexOf(transaction.id) > -1){
paid.push({
user : DBArray1[i],
transaction : transaction
});
break;
}
}
});
console.log(paid);

Categories