I am trying to populate a google chart. I have two values I am creating
- is an array of names that are contained in the value
- is an array of values contained in the data
I need to insert a 0 at the index where the value would be if it were present in the data to keep the data inline for the graph.
My data:
const MOCK = {
data: [
{date: "Aug.03", name: "name1", visits: 3 },
{date: "Aug.03", name: "name2", visits: 3 },
{date: "Aug.04", name: "name1", visits: 2 },
{date: "Aug.05", name: "name1", visits: 3 },
{date: "Aug.05", name: "name2", visits: 3 },
{date: "Aug.05", name: "name3", visits: 3 },
{date: "Aug.06", name: "name1.", visits: 7 },
{date: "Aug.06", name: "name3", visits: 8 },
{date: "Aug.07", name: "name2", visits: 1 },
{date: "Aug.07", name: "name3", visits: 13 },
{date: "Aug.08", name: "name2", visits: 12 },
{date: "Aug.08", name: "name3", visits: 15 },
]
}
Name array:
// create an array with each name
const nameGroups = MOCK.data.map((item) => item.name);
// remove duplicates from nameGroups
const cleanNameGroups = [...new Set(nameGroups)];
// add empty string for axis label
const finalNames = ["", ...cleanNameGroups]
console.log(finalNames)
// ["", "name1", "name2", "name3"]
Second Array Group:
const dateGroups = Object.entries(MOCK.data.reduce((acc, { date, ...item }) => ({
...acc,
[date]: [...(acc[date] || []), item],
}), {})).map(([key, value]) => [key, ...Object.values(value.map(value => value.visits))]);
console.log(dateGroups)
[["Aug.03", 3,3],["Aug.04",2],["Aug.05", 3, 3 ]]
So I need to insert a 0 where the values are missing for their corresponding name so that each array in dateGroups is the same length
I am trying to get dateGroups to look like:
[["Aug.03", 3,3,0],["Aug.04",2,0,0],["Aug.05",0, 3, 3 ]...]
CodePudding user response:
You can do this by reducing the array to a dictionary of {date: {names:visits}}
, then we can loop over the properties in that dictionary to to create the output you're looking for.
Use the set of names
finalNames
to create a base default objectnewObj
that'll be set for each date in the dictionary.- We first
map
the name array to[name, 0]
, i.e.[[name1, 0], [name2, 0]]
- Then we create an object from that array using
Object.fromEntries
. I logged that object to the console in the code.
- We first
Reduce the data array into a dictionary/object.
- Check if the dictionary has an property for the current row's date:
- If not, set it to
newObj
that we just made.
- If not, set it to
- Add the visit amount to the appropriate name in the object
- Check if the dictionary has an property for the current row's date:
Use
for in
to loop through the dates in the dictionary, and useObject.values
to convert{name1: 1, name2: 0, name3: 3}
to[1,0,3]
and push it with the property name, which is our date, into the an output array.
const MOCK = {
data: [
{date: "Aug.03", name: "name1", visits: 3 },
{date: "Aug.03", name: "name2", visits: 3 },
{date: "Aug.04", name: "name1", visits: 2 },
{date: "Aug.05", name: "name1", visits: 3 },
{date: "Aug.05", name: "name2", visits: 3 },
{date: "Aug.05", name: "name3", visits: 3 },
{date: "Aug.06", name: "name1", visits: 7 },
{date: "Aug.06", name: "name3", visits: 8 },
{date: "Aug.07", name: "name2", visits: 1 },
{date: "Aug.07", name: "name3", visits: 13 },
{date: "Aug.08", name: "name2", visits: 12 },
{date: "Aug.08", name: "name3", visits: 15 },
]
}
const nameGroups = MOCK.data.map((item) => item.name);
const cleanNameGroups = [...new Set(nameGroups)];
const finalNames = [ ...cleanNameGroups]
const newObj = Object.fromEntries(finalNames.map(name => [name,0])) // Defualt object for each date. Initializes all visit quantities to 0.
console.log('New Object: ', newObj)
const dateDict = MOCK.data.reduce((acc, obj) => {
if (!acc[obj.date]) {
acc[obj.date] = {...newObj}
}
acc[obj.date][obj.name] = obj.visits;
return acc
},{})
console.log('Date Dictionary: ', dateDict);
let output = []
for (let date in dateDict) {
let visitArray = Object.values(dateDict[date])
output.push([date, ...visitArray])
}
console.log('Output: ', output)