Home > Mobile >  JavaScript count number of ocurrences in Array of Objects
JavaScript count number of ocurrences in Array of Objects

Time:09-06

I have an array of objects and I was trying to figure out how I can create a new array of objects that would display a new array of objects, but with an "occurences" field.

Here is my starting json array of objects:

const fakeJson = [
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-10",
    "Popularity": 99,
    "Country": "Canada"
  },
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-11",
    "Popularity": 99,
    "Country": "Canada"
  },
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-12",
    "Popularity": 99,
    "Country": "Canada"
  },
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-12",
    "Popularity": 99,
    "Country": "China"
  },
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-12",
    "Popularity": 99,
    "Country": "Canada"
  }

Example result of what I would like. Notice the for Country Canada, one of them has Occurences: 2 for Date_Available "2022-04-12". How would I be able to accomplish this?

const resultJSON = [
  {
    "Date_Available": "2022-04-10",
    "Popularity": 99,
    "Country": "Canada",
    "Occurrences" : 1
  },
  {
    "Date_Available": "2022-04-11",
    "Popularity": 99,
    "Country": "Canada",
    "Ocurrences" : 1
  },
  {
    "Date_Available": "2022-04-12",
    "Popularity": 99,
    "Country": "Canada",
    "Occurrences" : 2
  },
  {
    "Date_Available": "2022-04-12",
    "Popularity": 99,
    "Country": "China",
    "Occurrences" : 1
  }

Here is what I have so far. My idea was to create a temporary obj with the country name, date available and occurrence set default to 1. Then based on the Date_Available, increase by 1 every time it appeared. However, if China and Canada both have the same date, then it seems to mess up the code and does not properly print the result.

let countNameMapping = {};
let finalArr = [];

for(let i = 0; i < fakeJson.length; i  ){
  let tempObj = {Country:fakeJson[i].Country, Date_Available: fakeJson[i].Date_Available, occurence: 1};
  let countryName = fakeJson[i].Country;
  let date = fakeJson[i].Date_Available;
  if(countNameMapping[date] === undefined){
    countNameMapping[countryName] = tempObj;
  } else {
    countNameMapping[date].occurence  = 1;
  }
}

for(let k in countNameMapping){
  finalArr.push(countNameMapping[k])
}

console.log(finalArr)

CodePudding user response:

  1. Group by a custom key, eg Date_Available Country
  2. reduce() the result, create an array with the first object as base, then add Ocurrences, based on the amount of objects found (.length)

const data = [{"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-10", "Popularity": 99, "Country": "Canada"}, {"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-11", "Popularity": 99, "Country": "Canada"}, {"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-12", "Popularity": 99, "Country": "Canada"}, {"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-12", "Popularity": 99, "Country": "China"}, {"Id": 1, "Name": "John", "Age": 32, "Date_Available": "2022-04-12", "Popularity": 99, "Country": "Canada"}];

const grouped = data.reduce((p, c) => {
    const key = c.Date_Available   c.Country;
    (p[key] = p[key] || []).push(c);
    return p;
}, {});

const result = Object.values(grouped).reduce((p, c) => [ ...p, { ...c[0], Ocurrences: c.length } ], []);

console.log(result)

Result:

[
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-10",
    "Popularity": 99,
    "Country": "Canada",
    "Ocurrences": 1
  },
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-11",
    "Popularity": 99,
    "Country": "Canada",
    "Ocurrences": 1
  },
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-12",
    "Popularity": 99,
    "Country": "Canada",
    "Ocurrences": 2
  },
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-12",
    "Popularity": 99,
    "Country": "China",
    "Ocurrences": 1
  }
]

CodePudding user response:

you can use reduce and Object.values for that

like this

const groupBy = (data, ...keyGroup) => Object.values(data.reduce((res, item) => {
const key = keyGroup.map(k => item[k]).join('-')
 const existing = res[key] || {...item, occurencies: 0}
 return {
   ...res,
   [key]: {...existing,occurencies: existing.occurencies   1 }
   
 }

}, {}))

const fakeJson = [
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-10",
    "Popularity": 99,
    "Country": "Canada"
  },
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-11",
    "Popularity": 99,
    "Country": "Canada"
  },
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-12",
    "Popularity": 99,
    "Country": "Canada"
  },
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-12",
    "Popularity": 99,
    "Country": "China"
  },
  {
    "Id": 1,
    "Name": "John",
    "Age": 32,
    "Date_Available": "2022-04-12",
    "Popularity": 99,
    "Country": "Canada"
  }
]

console.log('by ID', groupBy(fakeJson, 'Id'))
console.log('by Country', groupBy(fakeJson, 'Country'))
console.log('by country and date', groupBy( fakeJson, 'Country', 'Date_Available'))

CodePudding user response:

const json = fakeJson.reduce((prev, curr) => {
   const check = () => prev.findIndex(({ Date_Available, Country }) =>
      curr.Date_Available === Date_Available &&
      curr.Country === Country
   );

   if (
      !prev.length ||
      check() === -1
   ) prev.push({
         ...Object.fromEntries(
              Object.entries(curr).filter(([key]) => !key.match(/id|name|age/i))
         ),
         Occurences: 1
      })
   else prev[check()].Occurences  
   return prev
}, [])

console.log({ json });
  • Related