Related
I would like to know if there is a better way to deal with nested forEach when it comes to dealing with objects with properties that are nested arrays themselves.
My object (summarized):
{
...,
"tx_responses": [
{
...
"logs" : [
{
...,
"events": [
{
"type": "coin_received",
"attributes": [
{
"key": "receiver",
"value": "somesome"
},
{
"key": "amount",
"value": "somesome"
}
]
},
...
{
"type": "transfer",
"attributes": [
{
"key": "recipient",
"value": "somesome"
},
{
"key": "sender",
"value": "somesome"
},
{
"key": "amount",
"value": "somesome"
}
]
},
{
"type": "withdraw_rewards",
"attributes": [
{
"key": "amount",
"value": "somesomesomehere"
},
{
"key": "validator",
"value": "somesome"
}
]
},
...
]
}
],
...
I am essentially trying to extract all { key: 'amount', value: 'somesomesomehere' } objects in the "attributes" array of the "type" : "withdraw_rewards" object in the "events" array.
Currently this is the code I wrote to carry out my task:
getWithdrawnAmounts: async(del_addr_) => {
let withdrawnAmounts = [];
const res = await axios.get("some_url_that_uses_del_addr_");
res.data.tx_responses.forEach(txr => {
txr.logs.forEach(log => {
log.events.forEach(evnt => {
if (evnt.type == "withdraw_rewards") {
evnt.attributes.forEach(attr => {
if (attr.key == "amount") {
withdrawnAmounts.push(attr);
}
})
}
})
})
});
return withdrawnAmounts;
}
The code helps me to get what I need, but I was wondering if there is a better way to write my code so that I dont have to use so many nested .forEach methods. I was wondering if I should use .flat() or .flatMap() but I'm curious to know how would people approach this?
Thank you!
You are going to have to call some kind of iteration for each level you're going deeper.
Now, there is a more functional way to get the desired data, using flatMap and filter:
const data = { "tx_responses": [{ "logs": [{ "events": [{ "type": "coin_received", "attributes": [{ "key": "receiver", "value": "somesome" }, { "key": "amount", "value": "somesome" }]}, { "type": "transfer", "attributes": [{ "key": "recipient", "value": "somesome" }, { "key": "sender", "value": "somesome" }, { "key": "amount", "value": "somesome" }]}, { "type": "withdraw_rewards", "attributes": [{ "key": "amount", "value": "somesomesomehere" }, { "key": "validator", "value": "somesome" }]}]}]}]};
const result = data.tx_responses
.flatMap(r => r.logs
.flatMap(l => l.events.filter(e => e.type === 'withdraw_rewards')
.flatMap(e => e.attributes.filter(a => a.key === 'amount'))
)
);
console.log(result);
I am trying to the values from my data.json which consists of array of objects. I am trying to get the values by using map method on json data. My Json dat structure is like Array->Object->Array-Object([{[{}]}]). This is how the data is structured in Json. I have written down the Json data and logic to get the values down. Whenever I am trying to get the values from (inner array of object) I am ending up with undefined. Any one could assist me how to resolve this issue. Thanks in advance!
[
{
"key": "row-0",
"cells": [
{
"key": "cell-0",
"id": "ID-0",
"headerName": "Name",
"CustomerName": "ABC"
},
{
"key": "cell-1",
"id": "ID-1",
"headerName": "RegID",
"CustomerID": "P-01"
},
{
"key": "cell-2",
"id": "ID-2",
"headerName": "Detail",
"Deatil": "Abc"
}
]
},
{
"key": "row-1",
"cells": [
{
"key": "cell-1",
"id": "ID-1",
"headerName": "Name",
"CustomerName": "CDE"
},
{
"key": "cell-2",
"id": "ID-2",
"headerName": "RegID",
"CustomerID": "P-02"
},
{
"key": "cell-3",
"id": "ID-3",
"headerName": "Detail",
"Deatil": "CDE"
}
]
}
]
//Logic
{mockData.map((values, index) => {
console.log("VALUES", values);
return values.cells.map(({ headerName, ...rest }) => {
console.log("JSON", JSON.stringify(rest));
console.log("REST", rest.CustomerName);---> getting undefined(I tried many approach everything is giving me undefined)
});
})}
I have created an example for you
As mentioned in the above comment.. elements without customerName will give undefined.
let mockData = [{
"key": "row-0",
"cells": [{
"key": "cell-0",
"id": "ID-0",
"headerName": "Name",
"CustomerName": "ABC"
},
{
"key": "cell-1",
"id": "ID-1",
"headerName": "RegID",
"CustomerID": "P-01"
},
{
"key": "cell-2",
"id": "ID-2",
"headerName": "Detail",
"Deatil": "Abc"
}
]
},
{
"key": "row-1",
"cells": [{
"key": "cell-1",
"id": "ID-1",
"headerName": "Name",
"CustomerName": "CDE"
},
{
"key": "cell-2",
"id": "ID-2",
"headerName": "RegID",
"CustomerID": "P-02"
},
{
"key": "cell-3",
"id": "ID-3",
"headerName": "Detail",
"Deatil": "CDE"
}
]
}
];
mockData.map((values, index) => {
console.log("VALUES", values);
return values.cells.map(({
headerName,
...rest
}) => {
console.log("JSON",rest);
console.log("Key:", rest.key);
console.log("ID:", rest.id);
console.log("CustomerName:", rest.CustomerName ? rest.CustomerName : 'NA' );
});
})
I have a JSON like this, how to get the value of StatusDescription? I tried many times but the result is undefined. Here is my JSON:
{
"meta": {
"a2": 200,
"ta": "dasd",
"asdd": "asdda"
},
"data": {
"items": [
{
"id": "",
"number": "",
"origin_info": {
"ItemReceived": "2021-10-02 02:07:49",
"phone": 123456789,
"trackinfo": [
{
"StatusDescription": "what i need",
"Details": "",
"substatus": "ok"
},
{
"StatusDescription": "what i need",
"Details": "",
"substatus": "ok"
}
]
},
"destination_info": null,
"lastEvent": "grgrgrgrgr",
"lastUpdateTime": "mewmemew"
}
]
}
}
I'm using in my NodeJS app, like myapp.js, and console.log()
Try this
I stored your sample json in variable json
var json = {
"meta": {
"a2": 200,
"ta": "dasd",
"asdd": "asdda"
},
"data": {
"items": [
{
"id": "",
"number": "",
"origin_info": {
"ItemReceived": "2021-10-02 02:07:49",
"phone": 123456789,
"trackinfo": [
{
"StatusDescription": "what i need",
"Details": "",
"substatus": "ok"
},
{
"StatusDescription": "what i need",
"Details": "",
"substatus": "ok"
}
]
},
"destination_info": null,
"lastEvent": "grgrgrgrgr",
"lastUpdateTime": "mewmemew"
}
]
}
}
Accessed it like below
console.log(json.data.items[0].origin_info.trackinfo[0].StatusDescription);
Items is an array and we took array element 0.
trackinfo again is an array and we took array element 0.
We can change array index or loop through and get required values.
You have to iterate through your items and trackinfo to get to StatusDescription. Try this one.
const data = {
"meta": {
"a2": 200,
"ta": "dasd",
"asdd": "asdda"
},
"data": {
"items": [
{
"id": "",
"number": "",
"origin_info": {
"ItemReceived": "2021-10-02 02:07:49",
"phone": 123456789,
"trackinfo": [
{
"StatusDescription": "what i need",
"Details": "",
"substatus": "ok"
},
{
"StatusDescription": "what i need",
"Details": "",
"substatus": "ok"
}
]
},
"destination_info": null,
"lastEvent": "grgrgrgrgr",
"lastUpdateTime": "mewmemew"
}
]
}
}
const items = data.data.items.map(item => item)
const trackinfo = items.map(item => item.origin_info.trackinfo).flat()
console.log(trackinfo)
const statusDescription = trackinfo.map(trackinfo => trackinfo.StatusDescription)
console.log(statusDescription)
I have an array of object and another object containing labels, how to write a simple function to compare both array and replace the key name.
input = [
{
"id": "AAP",
"prd": "PL",
"trcode": "NORTH",
"accountNo": "12345",
"prBranch": null,
"prDealer": "Dealer 1",
"prUser": "CFG",
"staticBranch": "YES",
"staticCustomer": "NO",
"reason": "Invalid request"
},
{
"id": "AAC",
"prd": "PL",
"trcode": "WEST",
"accountNo": "67890",
"prBranch": null,
"prDealer": "Dealer 2",
"prUser": "DFG",
"staticBranch": "YES",
"staticCustomer": "NO",
"reason": "Invalid request"
}
],
labels = [
{
"key": "id",
"value": "USER"
},
{
"key": "prd",
"value": "PRODUCT"
},
{
"key": "trcode",
"value": "TRANSFER_CODE"
},
{
"key": "accountNo",
"value": "ACCOUNT_NUMBER"
},
{
"key": "prBranch",
"value": "PROCESSING_BRANCH"
},
{
"key": "prDealer",
"value": "PROCESSING_DEALER"
},
{
"key": "prUser",
"value": "PROCESSING_USER"
},
{
"key": "staticBranch",
"value": "STATIC_BRANCH"
},
{
"key": "staticAgent",
"value": "STATIC_AGENT"
},
{
"key": "reason",
"value": "Reason"
}
]
Expected output =
[
{
"USER": "AAP",
"PRODUCT": "PL",
"TRANSFER_CODE": "NORTH",
"ACCOUNT_NUMBER": "12345",
"PROCESSING_BRANCH": null,
"PROCESSING_DEALER": "Dealer 1",
"PROCESSING_USER": "CFG",
"STATIC_BRANCH": "YES",
"STATIC_CUSTOMER": "NO",
"Reason": "Invalid request"
},
{
"USER": "AAC",
"PRODUCT": "PL",
"TRANSFER_CODE": "WEST",
"ACCOUNT_NUMBER": "67890",
"PROCESSING_BRANCH": null,
"PROCESSING_DEALER": "Dealer 2",
"PROCESSING_USER": "DFG",
"STATIC_BRANCH": "YES",
"STATIC_CUSTOMER": "NO",
"Reason": "Invalid request"
}
],
You can use Array#map to convert each object in the array. For each object, we can map over the entries of the object and use Array#find to look for the replacement key if it exists. Finally, Object.fromEntries converts the array of key-value pairs back to an object.
let input=[{id:"AAP",prd:"PL",trcode:"NORTH",accountNo:"12345",prBranch:null,prDealer:"Dealer 1",prUser:"CFG",staticBranch:"YES",staticCustomer:"NO",reason:"Invalid request"},{id:"AAC",prd:"PL",trcode:"WEST",accountNo:"67890",prBranch:null,prDealer:"Dealer 2",prUser:"DFG",staticBranch:"YES",staticCustomer:"NO",reason:"Invalid request"}],labels=[{key:"id",value:"USER"},{key:"prd",value:"PRODUCT"},{key:"trcode",value:"TRANSFER_CODE"},{key:"accountNo",value:"ACCOUNT_NUMBER"},{key:"prBranch",value:"PROCESSING_BRANCH"},{key:"prDealer",value:"PROCESSING_DEALER"},{key:"prUser",value:"PROCESSING_USER"},{key:"staticBranch",value:"STATIC_BRANCH"},{key:"staticAgent",value:"STATIC_AGENT"},{key:"reason",value:"Reason"}];
const res = input.map(o =>
Object.fromEntries(Object.entries(o)
.map(([k,v])=>[labels.find(({key})=>key===k)?.value ?? k, v])));
console.log(res)
.as-console-wrapper{max-height:100%!important;top:0}
Loop through input and inside the loop use a for...in loop to loop through each property.
Inside the loop, loop through labels and get the corresponding value to that property, set the value of the property to the new property and delete the previous property.
input.forEach(e => {
for (const l in e) {
var a;
labels.forEach(e => {
e.key == l && (a = e.value)
}), e[a] = e[l], delete e[l]
}
});
Demo:
input=[{id:"AAP",prd:"PL",trcode:"NORTH",accountNo:"12345",prBranch:null,prDealer:"Dealer 1",prUser:"CFG",staticBranch:"YES",staticCustomer:"NO",reason:"Invalid request"},{id:"AAC",prd:"PL",trcode:"WEST",accountNo:"67890",prBranch:null,prDealer:"Dealer 2",prUser:"DFG",staticBranch:"YES",staticCustomer:"NO",reason:"Invalid request"}];var labels=[{key:"id",value:"USER"},{key:"prd",value:"PRODUCT"},{key:"trcode",value:"TRANSFER_CODE"},{key:"accountNo",value:"ACCOUNT_NUMBER"},{key:"prBranch",value:"PROCESSING_BRANCH"},{key:"prDealer",value:"PROCESSING_DEALER"},{key:"prUser",value:"PROCESSING_USER"},{key:"staticBranch",value:"STATIC_BRANCH"},{key:"staticAgent",value:"STATIC_AGENT"},{key:"reason",value:"Reason"}];
input.forEach(e=>{for(const l in e){var a;labels.forEach(e=>{e.key==l&&(a=e.value)}),e[a]=e[l],delete e[l]}});
console.log(input);
One of the first thing I would to is to use an object instead of an array for your key association:
labels = {
"id": "USER",
"prd": "PRODUCT",
"trcode": "TRANSFER_CODE",
"accountNo": "ACCOUNT_NUMBER",
"prBranch": "PROCESSING_BRANCH",
"prDealer": "PROCESSING_DEALER",
"prUser": "PROCESSING_USER",
"staticBranch": "STATIC_BRANCH",
"staticAgent": "STATIC_AGENT",
"reason": "Reason"
}
Now if you want to map them to your new object you can do
function renameKeys(src) {
let entries = Object.entries(src)
let renamedEntries = entries.map(([key, value]) => [
labels[key] || key,
/* I added a fallback to the original key
if it's not found to avoid undefined keys */
value,
])
return Object.fromEntries(renamedEntries)
}
// and use it like so
console.log(input.map(renameKeys))
You can just iterate them and assign the values as below
for (var object of input) {
for (var mapping of labels) {
if (object[mapping.key] !== undefined) {
object[mapping.value] = object[mapping.key];
delete object[mapping.key];
}
}
}
console.log(input);
The way I'd do it would be:
const input = [{
"id": "AAP",
"prd": "PL",
"trcode": "NORTH",
"accountNo": "12345",
"prBranch": null,
"prDealer": "Dealer 1",
"prUser": "CFG",
"staticBranch": "YES",
"staticCustomer": "NO",
"reason": "Invalid request"
},
{
"id": "AAC",
"prd": "PL",
"trcode": "WEST",
"accountNo": "67890",
"prBranch": null,
"prDealer": "Dealer 2",
"prUser": "DFG",
"staticBranch": "YES",
"staticCustomer": "NO",
"reason": "Invalid request"
}
];
const labels = [{
"key": "id",
"value": "USER"
},
{
"key": "prd",
"value": "PRODUCT"
},
{
"key": "trcode",
"value": "TRANSFER_CODE"
},
{
"key": "accountNo",
"value": "ACCOUNT_NUMBER"
},
{
"key": "prBranch",
"value": "PROCESSING_BRANCH"
},
{
"key": "prDealer",
"value": "PROCESSING_DEALER"
},
{
"key": "prUser",
"value": "PROCESSING_USER"
},
{
"key": "staticBranch",
"value": "STATIC_BRANCH"
},
{
"key": "staticAgent",
"value": "STATIC_AGENT"
},
{
"key": "reason",
"value": "Reason"
}
]
// 1. create an object mapping the old labels to the new ones
const betterLabels = labels.reduce((outObj, item) => {
outObj[item.key] = item.value;
return outObj;
}, {});
// 2. use `Array.prototype.map` to traverse the input array
// and `Array.prototype.reduce` with the label mapping object
// to generate the output array
const output = input.map(item => {
return Object.entries(item).reduce((newItem, [key, value]) => {
betterLabels[key]
? newItem[betterLabels[key]] = value
: newItem[key] = value
return newItem
}, {});
});
//test
console.log(output);
I have a JavaScript array with the following format:
[
{
"header": true,
"id": "0",
"name": "dairy",
},
{
"category": "dairy",
"header": false,
"id": "-LSlje6ESGALGpckMhb7",
"name": "milk",
},
{
"category": "dairy",
"header": false,
"id": "-LSm9EpFg5DhW036aUle",
"name": "cheese",
},
{
"header": true,
"id": "3",
"name": "dessert",
},
{
"category": "dessert",
"header": false,
"id": "-LSm9MLZkrnvtPySw5U6",
"name": "cake",
},
{
"category": "dessert",
"header": false,
"id": "-LSmAQ0rdDLrpz0TSPuD",
"name": "pie",
},
{
"header": true,
"id": "6",
"name": "fruit",
},
{
"category": "fruit",
"header": false,
"id": "-LSlazVIGAKLakxAIa8G",
"name": "apple",
},
{
"category": "fruit",
"header": false,
"id": "-LSlb5GH6xZz-DpNVS22",
"name": "pear",
},
{
"category": "fruit",
"header": false,
"id": "-LSwWJldY1nxQrotyv-V",
"name": "strawberry",
},
{
"header": true,
"id": "10",
"name": "meat",
},
{
"category": "meat",
"header": false,
"id": "-LSljXQzfXthJbOA54Ah",
"name": "fish",
},
{
"category": "meat",
"header": false,
"id": "-LSmA2-R9pOY8abAUyST",
"name": "steak",
},
{
"category": "meat",
"header": false,
"id": "-LSmAJ4J4gIfVQ8sgPDa",
"name": "pork",
},
]
What I am trying to do, is map through this array, and transform it to the following format:
[
{
title: nameOfFirstHeader,
data: items.slice(indexOfFirstHeader, indexOfSecondHeader),
},
{
title: nameOfSecondHeader,
data: items.slice(indexOfSecondHeader, indexOfThirdHeader),
},
{
title: nameOfThirdHeader,
data: items.slice(indexOfThirdHeader, indexOfFourthHeader),
},...and so on
]
So basically there will be an object section for each 'header' that is found in the original array. Each object section data property will contain the items found between the first header and the second header, and so on, until there are no more headers. I really can't wrap my head around how I can do this. Here is a reference to the the module I am using: https://github.com/saleel/react-native-super-grid#sectiongrid-example
Thanks!
I think this may be what you're trying to accomplish...
var grouped = items.reduce((acc,obj)=>{
let {header, name} = obj;
if (header) return [...acc, { title:name, data:[] }] // either first matching header or new match. Add fresh 'header' object
if (!acc.length) return acc; //not header and none have passed. Do nothing
let allButLast = acc.slice(0, acc.length-1),
lastElem = acc[acc.length-1]; // not a header, but there is an existing match. Add it to last match's data array
return [
...allButLast,
{
...lastElem,
data:[...lastElem.data, obj]
}
]
},[])
but it seems unreliable to trust the order of an array for this purpose. It would probably be more reliable to match by isHeader.name === notHeader.category to be less presumptive about the order of data you're iterating over. Like this...
var grouped = items.reduce((acc,obj)=>{
let {header, name, category} = obj;
if (header) return [...acc, { title:name, data:[] }];
if (!acc.length) return acc;
return acc.map((elem)=>{
if (elem.title !== category) return elem;
return {
...elem,
data: [ ...elem.data, obj]
};
})
},[])
I think you can probably do something like
const data = [];
let activeIndexForData = -1;
for(let i = 0; i < dataToSort.length -1; i++) {
if(dataToSort[i].header) {
activeIndexForData++;
}
if(data.length < activeIndexForData - 1) {
data.push({ title: dataToSort[i].name, data# []})
}
else {
data[activeIndexForData].data.push({ title: dataToSort[i].name, data: [])
}
}