I'm trying to use reduce to create an object that contains the percentage of presence of various countries in a list.
input:
countriesList = ["US","US","US","UK","IT","IT"]
desidered output:
percCountriesList = [{"country": "US", "weight": 0.5}, {"country": "UK", "weight": 0.1666}, {"country": "IT", "weight": 0.3333}]
How I calculate the percentage:
const countriesList = ["US","US","US","UK","IT","IT"]
const weightPercCountries = countriesList.reduce((pcts, x) => {
pcts[x] = (pcts, (pcts[x] ? pcts[x] : 0) 100 / countriesList.length);
return pcts;
}, []);
console.log(weightPercCountries)
So, I've got the percentages list:
[50, 16.666666666666668, 33.33333333...]
Now, how I can build the desidered output (country weight) "jsonized"? Thanks
CodePudding user response:
const countriesList = ["US","US","US","UK","IT","IT"]
const r = Object.values(countriesList.reduce((a,c,_,r)=>
(a[c]??={'country':c, weight:0},a[c].weight =1/r.length,a),{}))
console.log(r)
CodePudding user response:
First of all, your code produces an empty array (with a few additional properties), because the x
in your case is a country-shortcut and not an index. So if you do pcts[x] = ..
you are actually doing something like pcts['us'] = ...
which in most cases doesn't make too much sense for an array.
Second, if you want a complex object in you array, you need to create it somewhere ... See for instance the following snippet
I defined
reduce
to return anobject
, so I can easily check if the current country (defined byx
) is already contained or not.If it's not contained, I add a new property to the object, which already holds all properties I want in the result (ie
{ country: x, percentage: 0}
)Now, that I made sure, an object for the current country exists, I can access it via its name and update the percentage. Whether you want
50
or0.5
is up to you. Leave or remove the final/100
accordingly.reduce
now returns an object like{ "us": { country: "us", percentage: 0.5}, "it": { country: "it", percentage: 0.33} ... }
So to get an array of the values just use
Object.values(...)
which returns all enumerable properties of an object as an array
const
countriesList = ["US","US","US","UK","IT","IT"];
const
weightPercCountries = Object.values(countriesList.reduce((pcts, x) => {
if (!(x in pcts))
pcts[x] = { country: x, percentage: 0}
pcts[x].percentage = (100 / countriesList.length) / 100;
return pcts;
}, {}));
console.log(weightPercCountries)
Of course you can shorten the callback of the reduce
(like for instance in Andrew Park's answer). But for sake of readability (especially for someone who seems to be a beginner) I decided in favour of the more explicit code ...