It already shows the correct percentage. However, this is what it looks like:
8.333333333333332
How can I make it display like this: 8.33%
Putting it inside this will cause an error:
acc[key] = (acc[key] || 0) + (1 / totalUsers) * 100.toFixed(2);
Below are the codes:
const movies = data.filter(v => v.genre?.selected == "Movie");
const counts = movies.reduce((acc, cur) => {
return !cur["1"]?.drama
? acc:
Object.entries(cur["1"].drama).reduce((acc, [key,value]) => {
if (value) {
acc[key] = (acc[key] || 0) + (1 / totalUsers) * 100;
}
return acc;
}, acc)
}, {})
This is a part of the data:
const totalUsers = 12
const data = [{
"1": { drama: { Comedy: true, Romance: true, BuddyComedy: false } },
"2": {
drama2: { Tragedy: true},
others: "Dystopian",
},
id: "zaMR9TR7hNV3p3VFNumyNbXMto93",
genre: {
selected: "Movie",
},
displayName: "p1"
},
{
"1": { drama: { Tragedy: true, Comedy : true} },
"2": {
drama2: { Romance: true}
},
id: "zaMR9TR7hNV3p3VFNumyNbXMto93", //sample id
genre: {
selected: "Movie",
},
displayName: "p2"
}]
You have to wrap the 100 in brackets.
If you don't, the interpreter believes the number is a decimal, and tries to parse the segment after the period ("toFixed(2)") as a number, causing an error.
In your case...
You'll have to parse the number using the Number constructor, then call toFixed():
Number(+(acc[key] || 0) + (1 / totalUsers) * (100)).toFixed(2);
Take note of the unary plus operator before "(acc[key] || 0)" used to parse it into a number, to ensure that we aren't concatenating strings. (if you don't add it, you'll end up with NaN)
Working code:
const totalUsers = 12
const data=[{1:{drama:{Comedy:!0,Romance:!0,BuddyComedy:!1}},2:{drama2:{Tragedy:!0},others:"Dystopian"},id:"zaMR9TR7hNV3p3VFNumyNbXMto93",genre:{selected:"Movie"},displayName:"p1"},{1:{drama:{Tragedy:!0,Comedy:!0}},2:{drama2:{Romance:!0}},id:"zaMR9TR7hNV3p3VFNumyNbXMto93",genre:{selected:"Movie"},displayName:"p2"}];
const movies = data.filter(v => v.genre?.selected == "Movie");
const counts = movies.reduce((acc, cur) => {
return !cur["1"]?.drama ?
acc :
Object.entries(cur["1"].drama).reduce((acc, [key, value]) => {
if (value) {
acc[key] = Number(+(acc[key] || 0) + (1 / totalUsers) * (100)).toFixed(2);
}
return acc;
}, acc)
}, {})
console.log(JSON.stringify(counts,0, 2))
You loose precision if you repeatedly round the number and parse it throughout the calculation. To preserve the precision of your numbers as much as possible, rounding should only be done once after all calculation completed.
const totalUsers = 12
const data=[{1:{drama:{Comedy:!0,Romance:!0,BuddyComedy:!1}},2:{drama2:{Tragedy:!0},others:"Dystopian"},id:"zaMR9TR7hNV3p3VFNumyNbXMto93",genre:{selected:"Movie"},displayName:"p1"},{1:{drama:{Tragedy:!0,Comedy:!0}},2:{drama2:{Romance:!0}},id:"zaMR9TR7hNV3p3VFNumyNbXMto93",genre:{selected:"Movie"},displayName:"p2"}];
const movies = data.filter(v => v.genre?.selected == "Movie");
const counts = movies.reduce((acc, cur) => {
return !cur["1"]?.drama ?
acc :
Object.entries(cur["1"].drama).reduce((acc, [key, value]) => {
if (value) {
acc[key] = (acc[key] || 0) + (1 / totalUsers) * 100;
}
return acc;
}, acc)
}, {})
const rounded = Object.entries(counts).reduce((acc,[key,value])=>{
return {...acc,[key]:value.toFixed(2)};
},{});
console.log(rounded);
acc[key] = ((acc[key] || 0) + (1 / totalUsers) * 100).toFixed(2);
Wrap the whole thing in brackets and then put .toFixed(2)
const movies = data.filter(v => v.genre?.selected == "Movie");
const counts = movies.reduce((acc, cur) => {
return !cur["1"]?.sideEffects1
? acc:
Object.entries(cur["1"].drama).reduce((acc, [key,value]) => {
if (value) {
acc[key] = ((acc[key] || 0) + (1 / totalUsers) * 100).toFixed(2);
}
return acc;
}, acc)
}, {})