Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to group and transform an array based on multiple keys in javascript?

Tags:

Hi I am new to javascript, I want to change a the format of my array to a new format as part of my project.Here's my code

var array=[      
  {  Indicator: "Population National (% of population)", Country: "India", Year: "2012", Value: "98.8" },
  {  Indicator: "Population National (% of population)", Country: "India", Year: "2013", Value: "99.1" },
  {  Indicator: "Population National (% of population)", Country: "Japan", Year: "2012", Value: "99.2" },
  {  Indicator: "Population National (% of population)", Country: "Japan", Year: "2013", Value: "99.3" },
  {  Indicator: "Population National (% of population)", Country: "China", Year: "2012", Value: "99.4" },
  {  Indicator: "Population National (% of population)", Country: "China", Year: "2013", Value: "99.8" },

  {  Indicator: "Population Rural (% of population)", Country: "India", Year: "2012", Value: "97.9" },
  {  Indicator: "Population Rural (% of population)", Country: "India", Year: "2013", Value: "98.2" },
  { Indicator: "Population Rural (% of population)", Country: "Japan", Year: "2012", Value: "98.4" },
  {  Indicator: "Population Rural (% of population)", Country: "Japan", Year: "2013", Value: "98.7" },
  {  Indicator: "Population Rural (% of population)", Country: "China", Year: "2012", Value: "99.0" },
  {  Indicator: "Population Rural (% of population)", Country: "China", Year: "2013", Value: "98.0" },

  {  Indicator: "Population Urban (% of population)", Country: "India", Year: "2012", Value: "99.3" },
  {  Indicator: "Population Urban (% of population)", Country: "India", Year: "2013", Value: "93.6" },
  {  Indicator: "Population Urban (% of population)", Country: "Japan", Year: "2012", Value: "99.6" },
  {  Indicator: "Population Urban (% of population)", Country: "Japan", Year: "2013", Value: "97.6" },
  { Indicator: "Population Urban (% of population)", Country: "China", Year: "2012", Value: "95.6" },
  { Indicator: "Population Urban (% of population)", Country: "China", Year: "2013", Value: "99.6" }];

I need to change this as following

    var array=[{"Country":"India", "Indicator": "Population National (% of population)","2012": "98.8","2013": "99.1"},
 {"Country":"India", "Indicator": "Population Rural (% of population)","2012": "97.9","2013": "98.2"},
 {"Country":"India", "Indicator": "Population Urban (% of population)","2012": "99.3","2013": "93.6"},
 {"Country":"Japan", "Indicator": "Population National (% of population)","2012": "99.2","2013": "99.3"},
 {"Country":"Japan", "Indicator": "Population Rural (% of population)","2012": "98.4","2013": "98.7"},
 {"Country":"Japan", "Indicator": "Population Urban (% of population)","2012": "99.6","2013": "97.6"},

 {"Country":"China", "Indicator": "Population National (% of population)","2012": "99.4","2013": "99.8"},
 {"Country":"China", "Indicator": "Population Rural (% of population)","2012": "99.0","2013": "98.0"},
 {"Country":"China", "Indicator": "Population Urban (% of population)","2012": "95.6","2013": "99.6"}
];

I tried each method and to loop through array to create new array but I couldn't accomplish the desired format.

This is what i did

var excelArr = [],tempCountryArr=[],tempIndicArr=[],tempYearArr=[];

_.each(array, function (val, i) {
  if (_.contains(tempCountryArr, val.Country) == false) {
    tempCountryArr.push(val.Country);
  }
  if (_.contains(tempIndicArr, val.Indicator) == false) {
    tempIndicArr.push(val.Indicator);
  }
  if (_.contains(tempYearArr, val.Year) == false) {
    tempYearArr.push(val.Year);
  }
});
for (var i = 0; i < tempCountryArr.length; i++) {
  var countrydata = _.filter(array, function (item) {
    return (item.Country == tempCountryArr[i] && item.Indicator == tempIndicArr[i]);
  });

  var indicator = [];
  for (var j = 0; j < countrydata.length; j++) {

    for (var k = 0; k < tempYearArr.length; k++) {
      var yrArr = "";
      var yeardata = _.filter(countrydata, function (item) {
        return (item.Year == tempYearArr[k] && item.Indicator == countrydata[j].Indicator && item.Country == tempCountryArr[i]);
      });
      yrArr = tempYearArr[k];
      if (yeardata.length > 0) {
        if (yeardata[0].Value != null && yeardata[0].Value != undefined && yeardata[0].Value != "NaN") {

          if (excelArr.length != 0 && excelArr[j] != undefined) {
            excelArr[j][yrArr] = yeardata[0].Value;
          } else {
            excelArr.push({ [yrArr]: yeardata[0].Value });
          }

        } else {
          if (excelArr.length != 0 && excelArr[j] != undefined) {
            excelArr[j][yrArr] = "NA";
          }
          else {
            excelArr.push({ [yrArr]: "NA" });
          }

        }
      }
      else {
        if (excelArr.length != 0 && excelArr[j] != undefined) {
          excelArr[j][yrArr] = "NA";
        }
        else {
          excelArr.push({ yrArr: "NA" });
        }

      }
    }
    excelArr[j].Indicator = countrydata[j].Indicator.toString();
    excelArr[j]["Country"] = countrydata[j].Country;
  }
}

I am looking for any help.Thanks in advance

like image 389
Shins Avatar asked Feb 22 '19 07:02

Shins


1 Answers

You could use reduce and Object.values like this:

var array=[{Indicator:"Population National (% of population)",Country:"India",Year:"2012",Value:"98.8"},{Indicator:"Population National (% of population)",Country:"India",Year:"2013",Value:"99.1"},{Indicator:"Population National (% of population)",Country:"Japan",Year:"2012",Value:"99.2"},{Indicator:"Population National (% of population)",Country:"Japan",Year:"2013",Value:"99.3"},{Indicator:"Population National (% of population)",Country:"China",Year:"2012",Value:"99.4"},{Indicator:"Population National (% of population)",Country:"China",Year:"2013",Value:"99.8"},{Indicator:"Population Rural (% of population)",Country:"India",Year:"2012",Value:"97.9"},{Indicator:"Population Rural (% of population)",Country:"India",Year:"2013",Value:"98.2"},{Indicator:"Population Rural (% of population)",Country:"Japan",Year:"2012",Value:"98.4"},{Indicator:"Population Rural (% of population)",Country:"Japan",Year:"2013",Value:"98.7"},{Indicator:"Population Rural (% of population)",Country:"China",Year:"2012",Value:"99.0"},{Indicator:"Population Rural (% of population)",Country:"China",Year:"2013",Value:"98.0"},{Indicator:"Population Urban (% of population)",Country:"India",Year:"2012",Value:"99.3"},{Indicator:"Population Urban (% of population)",Country:"India",Year:"2013",Value:"93.6"},{Indicator:"Population Urban (% of population)",Country:"Japan",Year:"2012",Value:"99.6"},{Indicator:"Population Urban (% of population)",Country:"Japan",Year:"2013",Value:"97.6"},{Indicator:"Population Urban (% of population)",Country:"China",Year:"2012",Value:"95.6"},{Indicator:"Population Urban (% of population)",Country:"China",Year:"2013",Value:"99.6"}];
 
const merged = array.reduce((acc, { Indicator, Country, Year, Value }) => {
    const key = `${Country}-${Indicator}`
    acc[key] = acc[key] || { Country, Indicator }
    acc[key][Year] = Value;
    return acc
}, {})

const output = Object.values(merged);
console.log(output)

The idea is to create an accumulator object with keys equal to each unique combination of Country and Indicator like this:

{
  "India-Population National (% of population)": {
    "2012": "98.8",
    "2013": "99.1",
    "Country": "India",
    "Indicator": "Population National (% of population)"
  },
  "India-Population Urban (% of population)": {..}
  ...
}

Then use Object.values to get those values in an array.

like image 95
adiga Avatar answered Nov 15 '22 06:11

adiga