Home > Software engineering >  JS - using reduce to create percentage of presence in an array
JS - using reduce to create percentage of presence in an array

Time:12-06

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

  1. I defined reduce to return an object, so I can easily check if the current country (defined by x) is already contained or not.

  2. 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})

  3. 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 or 0.5 is up to you. Leave or remove the final /100 accordingly.

  4. 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 ...

  • Related