Seeking advice how to process this nested JSON/Object - javascript

I have a nested JSON and want to end up with the result array, how is this possible? Any tips on how i can accomplish this? Do i need to use a nester for in/of loop? Higher order functions etc? I am new to nested objects, any tip or good reference will be appreaciated!
// const db shows the desired result once db.save() is called. I want it
to include the Date, Symbols (USD etc.) and the value of it - all wrapped inside their own object
const db = [
{ Date: '1999-01-05', AUD: 1.8944, SEK: 9.4025, USD: 1.179 },
{ Date: '1999-01-06', AUD: 1.882, SEK: 9.305, USD: 1.1743 },
];
// the json that i recieve upon fetching
const json = {
rates: {
'1999-01-08': {
AUD: 1.8406,
SEK: 9.165,
USD: 1.1659,
},
'1999-01-06': {
AUD: 1.882,
SEK: 9.305,
USD: 1.1743,
},
'1999-01-07': {
AUD: 1.8474,
SEK: 9.18,
USD: 1.1632,
},
'1999-01-05': {
AUD: 1.8944,
SEK: 9.4025,
USD: 1.179,
},
},
start_at: '1999-01-05',
base: 'EUR',
end_at: '1999-01-10',
};

Here's a solution using nested for loops and Object.entires to get a key/value pair from your object. It creates an array of objects just like your desired result. (Not in the exact order, as Javascript doesn't care for keeping objects sorted).
function save(data) {
const db = []
for (const [key, value] of Object.entries(data.rates)) {
rate = { 'Date': key }
for (const [_key, _value] of Object.entries(value)) {
rate[_key] = _value
}
db.push(rate)
}
return db
}
Usage; in your posted example, would be:
db = save(json)

Thanks for the answer, i didn't get it to work as i probably messed something up or explained poorly, apologise. But seeing you using nested for loop helped me figure out this approach which resulted in every currency and exchange rate from a specific date to be in one object with only key values.
const db = [];
for (const prop in json.rates) {
Object.keys(json.rates[prop]).forEach((element) => {
const obj = {
date: prop,
symbol: element,
rate: json.rates[prop][element],
base: json.base,
};
db.push(obj);
});
}
console.log(db);
enter code here
enter code here

Related

Taking an array of Objects and filtering each objects keys by an array of string

I am pulling backend data to my application, but i want the user to be able to select which keys they want to see. So i have been trying to build a way for them to generate an array of strings and have that be compared to each object in the array and output the new array of objects with each key excluded.
Here is the Filter array:
const filterData =
[
'TestOne',
'TestTwo',
]
Here is the array of objects:
const data = [
{
_id: "62ec2f1084c7f48175a9cb4a",
Date: "2022-08-04T15:41:37.567Z",
facilityId: "62e5a9fd45f2646fc7361fa3",
userId: "62e16d390f4685e4fdb6a288",
formData: {
Date: "2022-08-04T15:41:37.567Z",
TestOne: 60002,
TestTwo: 19998,
TestThree: 102,
TestFour: "True"
},
},
{
_id: "62ec2f1c84c7f48175a9cb58",
Date: "2022-08-04T15:41:52.932Z",
facilityId: "62e5a9fd45f2646fc7361fa3",
userId: "62e16d390f4685e4fdb6a288",
formData: {
Date: "2022-08-04T15:41:52.932Z",
TestOne: 60003,
TestTwo: 19997,
TestThree: 103,
TestFour: "True"
},
},
]
I want to build a function that takes the data.formData and filters out any keys that are not included in the filterData. I am having a hard time figuring out what exactly needs done to acheive this. If anyone could help id greatly appreciate it.
----EDIT----
Here is something of a process that i have thought of but it returns errors and cant really think of why.
const formObject =
datas.length > 0 &&
datas.map((data, i) => {
const filterData = ['TestOne', 'TestTwo']
filterData.map((filter) => {
delete data.formData[filter]
})
})
This function gives me errors of Uncaught TypeError: Cannot delete property 'TestThree' of #<Object>, ive tried making a new instance of datas but it doesnt work
I would do it this way:
const result = data.map(x => {
for (const [key, value] of Object.entries(x.formData)) {
if (!filterData.includes(key)) {
delete x.formData[key];
}
}
return x;
})
Hope this helps
The key highlights to this function are:
Before the first loop, the array is cloned✥ then each object is skimmed over to find "formData". Since the actual keys are known, I'm going on the logical assumption that the object that has them is known as well -- hence the second parameter path.
Object.keys(obj['formData']) = ["Date", "TestOne", "TestTwo", "TestThree", "TestFour"] :
Figure I
function filterData(array, path, ...keys) {
let clone = structuredClone(array);
for (let obj of clone) {
Object.keys(obj[path]).flatMap(key =>
//... obj[path] = [ {{["formData"]}}...
//... ["Date", "TestOne", "TestTwo", "TestThree", "TestFour"]
On the second loop, the keys form the first loop is checked vs. the third parameter ...keys, a rest parameter that consists of one or more keys to filter out. The if condition has been reversed with ! operator:
Figure II
if (![...keys].includes(key)) {
return [];
}
return delete obj[path][key];
✥The TypeError sounds like the object is frozen so by cloning the array you can freely work on the clone.
const data = [{
_id: "62ec2f1084c7f48175a9cb4a",
Date: "2022-08-04T15:41:37.567Z",
facilityId: "62e5a9fd45f2646fc7361fa3",
userId: "62e16d390f4685e4fdb6a288",
formData: {
Date: "2022-08-04T15:41:37.567Z",
TestOne: 60002,
TestTwo: 19998,
TestThree: 102,
TestFour: "True"
}
}, {
_id: "62ec2f1c84c7f48175a9cb58",
Date: "2022-08-04T15:41:52.932Z",
facilityId: "62e5a9fd45f2646fc7361fa3",
userId: "62e16d390f4685e4fdb6a288",
formData: {
Date: "2022-08-04T15:41:52.932Z",
TestOne: 60003,
TestTwo: 19997,
TestThree: 103,
TestFour: "True"
}
}];
/**
* Find any given number of keys and remove them
* #param {array<object>} array - An array of objects
* #param {string} path - Name of the key if the target object is one
* level down. (todo: recursive algorithm to dig deeper)
* #param {string/array<string>} keys - List of keys to filter out
* #return {array<object>} The array sans filtered keys
*/
function filterData(array, path, ...keys) {
let clone = structuredClone(array);
for (let obj of clone) {
Object.keys(obj[path]).flatMap(key => {
if (![...keys].includes(key)) {
return [];
}
return delete obj[path][key];
});
}
return clone;
}
let x = filterData(data, "formData", "Date", "TestFour");
console.log(x);

How to compare and organise object data in 3 separate arrays whilst removing duplicates

I have 3 different arrays which contain an object with public holiday data (based on the region in the world e.g Mexico, Canada, US). I want to organise the data (store a combination of it all in its own array) so that if a regions share the same public holiday for example name: 'Christmas Day' date: 2021-12-25 then it only stores this once rather than for each region which is what its doing at the moment. The main issue is theres a problem with a lot of duplicate data inside allPublicHolidays function & i'm getting lost when it comes to the checkIfSame forEach loop as there is probably a much nicer way to do this.
The array data looks like this per region:
[
{
date: '2021-05-31 00:00:00',
name: 'Spring bank holiday',
},
{
date: '2021-12-25 00:00:00',
name: 'Christmas Day',
},
{
date: '2021-12-26 00:00:00',
name: 'Boxing Day',
}
]
The idea I had is to use a forEach loop for each region which pushes the data from each to its own array but checks the array each time it processes a holiday to make sure it doesn't already exist within the array. Before pushing it calls a function to check if the name data is the same as the array.
Here is what I have so far:
const regionUS = usArrayData;
const regionMX = mxArrayData;
const regionCA = caArrayData;
let allPublicHolidays = [];
function checkIfSame(name1, array) {
let boolean = false;
if (array) {
array.forEach((arr) => {
if (name1 == arr.name) {
boolean = true;
}
})
}
return boolean;
}
regionUS.forEach((USholiday) => {
if (!checkIfSame(USholiday.name, allPublicHolidays)) {
allPublicHolidays.push(USholiday);
}
});
regionMX.forEach((MXholiday) => {
if (!checkIfSame(MXholiday.name, allPublicHolidays)) {
allPublicHolidays.push(MXholiday);
}
});
Any help with storing all data in one array minus duplicates based on object.name && object.date would be really appreciated.
Thank you

Different order of objects while looping individually and printing all at once

I have a response object, which has a key tags whose value is a json. I am trying to sort the json based on a key, then iterating through the list and pushing the objects to a react list. I see that when I print individually, they are coming as expected, but when I print as a whole, they are not in the same order.
sortTags: function (response) {
tagss = []
response.tags.sort((a, b) => a.disp_id - b.disp_id).map(function(tag) {
console.log(tag)
tagss.push(tag)
});
console.log(tagss)
return tagss;
}
I see that when I do console.log(tag), it is printing in the order as expected. But console.log(tagss) is printing in a different order.
The question maybe very naive. Please do help. Thank you, in advance.
You don't need map to do this. sort will return a newly created sorted array. You just have to clone the tags array using the spread operator ... and then return the sort result return response.tags.sort((a, b) => a.disp_id - b.disp_id).
Run snippet to see it in action
const resp = {
tags: [{
name: "Nikos",
disp_id: 45,
}, {
name: "Giorgos",
disp_id: 25,
}, {
name: "Adreas",
disp_id: 21,
}, {
name: "Maria",
disp_id: 67,
}, {
name: "Panos",
disp_id: 19,
}]
};
const Sorter = {
sortTags: function(response) {
return [...response.tags].sort((a, b) => a.disp_id - b.disp_id);
}
}
document.getElementById('result').textContent = JSON.stringify(
Sorter.sortTags(resp)
, null, 2);
<pre id="result"></pre>
You could just use the sort method and then if you want to clone the array, you could use concat.
response.tags.sort((a, b) => a.disp_id - b.disp_id)
tagss = [].concat(tags)

Merge Data from different Queries without duplicates

I am getting data from three different queries via Api. I want data to be merged without the duplicate data.
This is my function where i am merging the data:
getStaffCount(data) {
if (data == null || data.results === null )
return [];
else
return data.results.StaffCount.map(m => ({ Name: m.Name, Accounts: m.Accounts })).
concat(data.results.RepProviderAccount.map(m => ({ Name: m.Name, Accnt: m.Accnt }))).
concat( data.results.ProviderAccount.map(m => ({ Name: m.Name, Account: m.Account })));
}
This is my table:
<PowerTable Data={{ rows: this.getStaffCount(this.props.GridData) }} rowsPerPage={5} orderBy="Name" order="asc" >
<PowerColumn id='Name' columnName='Name' numeric={false} disablePadding={false} label='Profile Name' width={100}>
</PowerColumn>
<PowerColumn id='Accounts' columnName='Accounts' numeric={false} disablePadding={false} label='Staff Accounts' width={100}>
</PowerColumn>
<PowerColumn id='Account' columnName='Account' numeric={false} disablePadding={false} label='Provider Account' width={100} >
</PowerColumn>
<PowerColumn id='Accnt' columnName='Accnt' numeric={false} disablePadding={false} label='Rep Provider Account' width={100} >
</PowerColumn>
</PowerTable>
So in the above image same Profile Name(CNX MSL Platform) is coming twice. So is there any way i can merged those rows?
I want the Output in this way:
Profile Name Staff Provider Rep Provider
Cnx MSl Platform 2 1
Cnx Specilaity sales Platform 7 22
Data:
As an object
if the data is an object the easy way to do that is the spread opperator
const combinedData = {
...dataSrc1,
...dataSrc2,
...dataSrc3,
}
All matching keys will be overwritten by the previous
As an array
It's a bit more complex. Assuming your object has a unique id (or any value to identify 2 as the same item) you can use a Set since they can only have unique values.
const array = [
...dataSrc1,
...dataSrc2,
...dataSrc3,
]
const unique = [...new Set(array.map(item => item.id))];
Your answer to my question about what the data looks like and how to group them didn't make any sense, neither did you answer Joe just showed the json data and tell him where the data comes from instead of what it is.
So I assume you group by Name and Account is ignored. You can group them in the following way:
const data = {
results: {
StaffCount: [
{
Name: 'a',
Accounts: 2,
},
{
Name: 'b',
Accounts: 20,
},
],
RepProviderAccount: [
{
Name: 'a',
Accnt: 3,
},
],
ProviderAccount: [
{
Name: 'a',
Account: 1,
},
],
},
};
const grouped = [
...data.results.StaffCount,
...data.results.RepProviderAccount,
...data.results.ProviderAccount,
].reduce((result, item) => {
const {
Name,
Account = 0,
Accounts = 0,
Accnt = 0,
} = item;
const existing = result.get(item.Name) || {
Name,
Account: 0,
Accounts: 0,
Accnt: 0,
};
existing.Account += Account;
existing.Accounts += Accounts;
existing.Accnt += Accnt;
return result.set(Name, existing);
}, new Map());
console.log([...grouped.values()]);
In case this doesn't work for you can you please update your question and provide code as in my answer with the expected input and output? You can respond to this answer and I'll have a look at your question again.
This may actually be an xy problem, you are fetching 3 data sources and then trying to group and sum them but maybe you can just get 1 data source and try salesforce to group and sum them in the query. I don't know enough about salesforce but maybe you can ask another question tagging it with soql if it's possible to just get the data grouped and summed.

psuhing an object inside another object

I want to create an object of objects which should be something like this.
let data={
{ _id:10010,
value:"tom"
},
{
_id:2002,
value:22882
}
}
One solution that i could think of was this .
let data = {};
data.content = ({
_id: 1001,
value: "tom"
});
data.content = ({
id: 10001,
status: "harry"
});
console.log(data);
However if we do this we can only have one content inside our main object .Can we accomplish the desired data format while creating an object of objects ?
You can use array.
let data=[
{ _id:10010,
value:"tom"
},
{ _id:2002,
value:22882
}
]
data.push({
_id:1001,
value:"tom"
});
data.push({
_id:1001,
value:"tom"
});
Push method will add object to the array. If you need something else you can create more complex function/class that handles the requirements, but this maybe would be enough.
I assume you need to do with array
let data=[];
data.push({
_id:1001,
value:"tom"
});
data.push({
id:10001,
status:"harry"
});
console.log(data);
You cannot create an "object of objects". Objects store data in key:value pairs. You might consider creating an array of objects, after which you can reference the array items using indexes:
let data = [];
data.push({
_id: 10010,
value: "tom"
});
data.push({
_id: 2002,
value: 22882
});
console.log(data);
You can make use of arrays in order to achieve the result.
let data = [];
data[0]= {
_id:10010,
value:"tom"
}
data[1]= {
_id:2002,
value:22882
}
and so on...
I believe what you really mean is
let data={
10010: { _id:10010,
value:"tom"
},
2002: {
_id:2002,
value:22882
}
}
Property of objects has to be key value pair, meaning in order to have a object nested in an object, as a value, u need to pair it with a key. Hence using the id of object as the key to store it.
data['10010'] = { _id: 10010, value: 'tom' };
data['2002'] = { _id: 2002, value: 22882 };

Categories