Related
I have a JSON array that looks like this:
[{
"day":"all",
"client_first":"3",
"client_second":"2",
"client_third":"3"
},
{
"day":"monday",
"client_first":"2",
"client_second":"2",
"client_third":"2"
}]
I would like to transform the above into the following
[{
label: 'all',
data: [3,2,3]
},
{
label: 'monday',
data: [2,2,2]
}]
Thanks in advance
Given input:
const input = [{
"day":"all",
"client_first":"3",
"client_second":"2",
"client_third":"3"
},
{
"day":"monday",
"client_first":"2",
"client_second":"2",
"client_third":"2"
}];
Looks like the semantics of what you want to do align very well with Array.map.
For each values in the input array, map it to an object such that label is set by day (key rename), and put in to data the values of the other entries.
To get the entries (key,value pairs) we use Object.entries. We Array.filter to get those with key !== 'day'. We want an array of the values, so we map the filtered entries (key,value pairs) to only the values. The input is string, but looks like you want it as numbers, so we convert using Number function
const output = input.map(obj => ({
label: obj.day,
data: Object.entries(obj).filter(([key]) => key !== 'day').map(([, val]) => Number(val)),
}));
In one line of code:
arr.map(({day,...clients})=>({label:day,data:[Object.values(clients).map(Number)]})):
looping over array and getting the day using Destructuring from object and clients using rest_parameters
let arr = [{
"day":"all",
"client_first":"3",
"client_second":"2",
"client_third":"3"
},
{
"day":"monday",
"client_first":"2",
"client_second":"2",
"client_third":"2"
}];
console.log(arr.map(({day,...clients})=>({label:day,data:[Object.values(clients).map(Number)]})))
Overview
I need to make a chart in my react project.
Using data from a json (Object Array).
Example json:
[
{recruiter_id: 1, datetime_created: "1/01/2021", name: "Aaron"},
{recruiter_id: 2, datetime_created: "9/01/2021", name: "Bob"},
{recruiter_id: 1, datetime_created: "9/01/2021", name: "Aaron"},
{recruiter_id: 3, datetime_created: "20/01/2021", name: "Jane"}
]
Result object array structure required:
[
{name: name,
recruiter_id: recruiter_id,
week_qty: [0,2,1,0,2,0,0,0,0,0,0,0,0,1,0,0,0,...] },
...]
// week_qty will be an array of 52 to represent each week of the year. It will be a 0 if there was no dates for that week.
Goal
This is what the new object array should look like, if we used the example json.
[
{name: "Aaron", recruiter_id:1, week_qty: [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...]},
{name: "Bob", recruiter_id:2, week_qty: [0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...]},
{name: "Jane", recruiter_id:3, week_qty: [0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...]}
]
What I have
I dont have any working code yet. I am currently working on object[0] to attempt to put the dates into the 52 array. And then after that I will then turn it into a loop to work on each object. Once I have it semi working, I will post it for example.
--- Edit ---
var array = result
var flags = [], output = [], l = array.length, i;
for (i = 0; i < l; i++) {
if (flags[array[i].recruiter_id]) continue;
flags[array[i].recruiter_id] = true;
var temp = {}
temp.Recruiter_id = array[i].recruiter_id
temp.Name = array[i].name
temp.QTY = []
output.push(temp);
}
console.log("output : ", output)
This produces the new object array structure with the id and name filled out.
[
{name: name,
recruiter_id: recruiter_id,
week_qty: [] },
...]
It only has 1 object for each id
Now I need to work on getting the week numbers for the dates and put them into each of those objects.
Question
Any code suggestions on how to get this result?
Side Note
If your curious to know how I then plan on using the new object array to use with my chart.
I will let the user select the week. Lets say week 1.
I will then map through the object array and get the week_qty for index 1 and the name value of the object.
I will store that week_qty and the name in a new new object array.
That new new object array will then look like this
[{name: "Aaron",QTY: 2},{name: "Bob",QTY: 1,]
That will then be passed as the x and y value to the chart.
You can use reduce and increase the week counter after parsing each date and getting the week (using moment.js for that part here)
But you can see Get week of year in JavaScript like in PHP for more details on how to calculate it yourself
const data = [
{recruiter_id: 1, datetime_created: "1/01/2021", name: "Aaron"},
{recruiter_id: 2, datetime_created: "9/01/2021", name: "Bob"},
{recruiter_id: 1, datetime_created: "9/01/2021", name: "Aaron"},
{recruiter_id: 3, datetime_created: "20/01/2021", name: "Jane"}
];
const weekly = data.reduce((acc, item, index, array) => {
const {
recruiter_id,
datetime_created,
name
} = item;
let existing = acc.find(({
recruiter_id: id
}) => id === recruiter_id);
if (!existing) {
existing = {recruiter_id, name, week_qty:Array(52).fill(0)};
acc.push(existing);
}
const week = moment(datetime_created,'D/M/YYYY').week()-1;
existing.week_qty[week]++;
return acc;
}, []);
console.log(JSON.stringify(weekly))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous"></script>
I'm trying to render a chart from a big amount of data (about 1200 entries). The chart takes in an array of objects with text and value properties like the one shown in FIG1. The data that I have coming in though is an object with key value pairs of string and number like the one shown if FIG2.
How could I transform the data from FIG2 format to FIG1 format so that I can use it in the Chart? Any help is much appreciated.
//FIG1
let words = [
{
text: "told",
value: 64,
},
{
text: "great",
value: 11,
},
{
text: "thought",
value: 16,
},
{
text: "clean",
value: 17,
},
];
//FIG2
const data = {
"give it a try!": 97,
"go for 6 months and get 1 month free": 8,
"go for 12 months and get 2 month free": 2,
"go for 12 months and get 2 months free": 6,
"go to url": 1,
};
...
return (
<div>
<h1>Chart</h1>
<ReactWordcloud words={words} />
</div>
);
Easy-Peasy
const transformed = Object.entries(data).map(( [key, value] )=>{
return { text:key , value: value }
})
So I have an array with a data of
var today = "2020-08-31"
var array = [
{
name: "Joshua",
id: 1,
date: "2020-08-31"
},
{
name: "Michael",
id: 2,
date: "2020-09-1"
}]
I want to create a sectionList that the sectionHeader title will be depending on the date today and will compare it to the date value from the array. so for example the date from the array is "2020-08-31" and today's date is same as "2020-08-31" the title should be "Today" and tomorrow is "2020-09-01" and the date from the array is still "2020-08-31" the title should be "Yesterday" is it possible?? please help me. im stuck with this. Thank you!!!!
Use the parse function from the JS Date library to parse the date hence convert it into long and then return the string (yesterday, today, tomorrow).
Add the displayDate into you array in order to loop through and display the field's value.
const today = "2020-08-31"
let array = [{
name: "Joshua",
id: 1,
date: "2020-08-31"
},
{
name: "Michael",
id: 2,
date: "2020-09-1"
}
]
array = array.map(x => ({
...x,
displayDate: (() => {
if (Date.parse(today) < Date.parse(x.date)) {
return 'yesterday';
} else if (Date.parse(today) > Date.parse(x.date)) {
return 'tomorrow';
}
return 'today';
})()
}));
console.log(array)
I receive an array of posts through an API and want to merge the ones with the same "month" and "year" (day is not important), into one object. I looked up for answers but there are just too many foo-bar examples that confuses more than helping. I want to know the cleanest, most elegant way of handling such problems, without getting into call-back hell and nested blocks...
Here is the API response:
0:
{
date: {day: 27, month: 1, year: 2020}
id: 3
}
1:
{
date: {day: 28, month: 1, year: 2020}
id: 4
}
2:
{
date: {day: 31, month: 1, year: 2020}
id: 5
}
3:
{
date: {day: 1, month: 2, year: 2020}
id: 6
}
4:
{
date: {day: 2, month: 2, year: 2020}
id: 7
}
The expected outcome:
0:
result: {month: 1, year: 2020, id:[3,4,5]}
1:
result: {month: 2, year: 2020, id:[6,7]}
One approach would be to use the Array#reduce() method to transform the input array into a dictionary, where each value contains the accumulation of id's for that month and year. Once this dictionary has been built, you could then extract the values of that dictionary to an array via Object#values() to obtain the required output:
let input=[{date:{day:27,month:1,year:2020},id:3},{date:{day:28,month:1,year:2020},id:4},{date:{day:31,month:1,year:2020},id:5},{date:{day:1,month:2,year:2020},id:6},{date:{day:2,month:2,year:2020},id:7}];
/* Convert the dictionary that will be created by reduce to a value array */
var output = Object.values(input.reduce((dict, item) => {
const { date, id } = item;
/* The distinct key for this item based on month/year of date field */
const key = `${date.month}-${date.year}`;
/* Check if dictionary already has an object value for key. This short hand
will only insert a new object value for key, if one does not already exist
in the dictionary */
const value = dict[key] || { month : date.month, year : date.year, id : [] };
/* Add the item id to the dictionary entries id array */
value.id.push(id);
/* Update value object for key */
return { ...dict, [key] : value };
}, {}))
console.log(output);
The idea here is that the dictionary is built using Compound Keys, where the keys are derived from the month and year of the current array item.
When no value exists for the current key, a new value object is inserted to the dictionary for that key:
{ month : date.month, year : date.year, id : [] }
The id of the current array item is then added (accumulated) to the id sub array of the object for that key:
dict[key].id.push(id);
Hope that helps
Here is an alternate approach, if you are not a big fan of Array.reduce and Array.values and also, if you like to consider performance when running the response for a larger data set.
This approach avoids cloning object (or rather non-mutating object) with spread operator i.e {...<anyObject>} while iterating. which should be fine for minimal set of data but but definitely not when you deal with huge volume.
const response = [{
date: { day: 27, month: 1, year: 2020 },
id: 3
}, {
date: { day: 28, month: 1, year: 2020 },
id: 4
}, {
date: { day: 31, month: 1, year: 2020 },
id: 5
},{
date: { day: 1, month: 2, year: 2020 },
id: 6
},{
date: { day: 2, month: 2, year: 2020 },
id: 7
}];
function groupByMonthYear(response) {
// output
const groupedData = []
// Using map for lookup to avoid iterating again on the grouped data
const referenceMap = new Map();
// destructing month, year and id from the response
for (const { date: { month, year }, id } of response) {
const groupKey = `${month}${year}`
// check if the month and year reference is already seen using the groupKey MMYYYY
if (referenceMap.has(groupKey)) {
referenceMap.get(groupKey).id.push(id);
// early return
continue;
}
// simply add a new entry if it doesn't exist
const data = {
month,
year,
id: [id]
};
groupedData.push(data);
referenceMap.set(groupKey, data)
}
return groupedData;
}
// Invoke and Print the result
console.log(groupByMonthYear(response));