1

I have the following array

const arr = [{
  agrupacion: "Total país",
  valor: "81.8",
  year: 2015
}, {
  agrupacion: "Total país",
  valor: "86.4",
  year: 2016
}, {
  agrupacion: "Total país",
  valor: "67.3",
  year: 2017
}, {
  agrupacion: "Total país",
  valor: "70.8",
  year: 2018
}, {
  agrupacion: "Total país",
  valor: "67.6",
  year: 2019
}, {
  agrupacion: "Oriental",
  valor: "78.6",
  year: 2015
}, {
  agrupacion: "Oriental",
  valor: "83.1",
  year: 2016
}, {
  agrupacion: "Oriental",
  valor: "65.6",
  year: 2017
}, {
  agrupacion: "Oriental",
  valor: "68.1",
  year: 2018
}, {
  agrupacion: "Oriental",
  valor: "63.7",
  year: 2019
}, {
  agrupacion: "Occidental",
  valor: "177.3",
  year: 2015
}, {
  agrupacion: "Occidental",
  valor: "182.9",
  year: 2016
}, {
  agrupacion: "Occidental",
  valor: "114.3",
  year: 2017
}, {
  agrupacion: "Occidental",
  valor: "144.5",
  year: 2018
}, {
  agrupacion: "Occidental",
  valor: "169.9",
  year: 2019
}, {
  agrupacion: "Urbano",
  valor: "79.6",
  year: 2015
}, {
  agrupacion: "Urbano",
  valor: "92.5",
  year: 2016
}, {
  agrupacion: "Urbano",
  valor: "62.1",
  year: 2017
}, {
  agrupacion: "Urbano",
  valor: "82.2",
  year: 2018
}, {
  agrupacion: "Urbano",
  valor: "80.6",
  year: 2019
}, {
  agrupacion: "Rural",
  valor: "86.5",
  year: 2015
}, {
  agrupacion: "Rural",
  valor: "63.7",
  year: 2016
}, {
  agrupacion: "Rural",
  valor: "87.2",
  year: 2017
}, {
  agrupacion: "Rural",
  valor: "45.7",
  year: 2018
}, {
  agrupacion: "Rural",
  valor: "38.9",
  year: 2019
}];

I used this method to achieve what I wanted:

const groups = new Map(arr.map(({agrupacion}) => [agrupacion, { agrupacion }]));
for (const {agrupacion, valor, year} of arr) {
    groups.get(agrupacion)["col" + year] = +valor;
}

const result = [...groups.values()];

the output is (console.log(result )):

[{
  agrupacion: "Total país",
  col2015: 81.8,
  col2016: 86.4,
  col2017: 67.3,
  col2018: 70.8,
  col2019: 67.6
}, {
  agrupacion: "Oriental",
  col2015: 78.6,
  col2016: 83.1,
  col2017: 65.6,
  col2018: 68.1,
  col2019: 63.7
}, {
  agrupacion: "Occidental",
  col2015: 177.3,
  col2016: 182.9,
  col2017: 114.3,
  col2018: 144.5,
  col2019: 169.9
}, {
  agrupacion: "Urbano",
  col2015: 79.6,
  col2016: 92.5,
  col2017: 62.1,
  col2018: 82.2,
  col2019: 80.6
}, {
  agrupacion: "Rural",
  col2015: 86.5,
  col2016: 63.7,
  col2017: 87.2,
  col2018: 45.7,
  col2019: 38.9
}];

That output is the format I need however the problem comes when I add additional data with the same "agrupacion" value to my arr array, for example I add this at the end of my arr array

,{
  agrupacion: "Total país",
  valor: "151",
  year: 2015
}, {
  agrupacion: "Total país",
  valor: "184",
  year: 2016
}, {
  agrupacion: "Total país",
  valor: "165",
  year: 2017
}, {
  agrupacion: "Total país",
  valor: "147",
  year: 2018
}, {
  agrupacion: "Total país",
  valor: "190",
  year: 2019
}

This is what I need:

[{
  agrupacion: "Total país",
  col2015: 81.8,
  col2016: 86.4,
  col2017: 67.3,
  col2018: 70.8,
  col2019: 67.6
}, {
  agrupacion: "Oriental",
  col2015: 78.6,
  col2016: 83.1,
  col2017: 65.6,
  col2018: 68.1,
  col2019: 63.7
}, {
  agrupacion: "Occidental",
  col2015: 177.3,
  col2016: 182.9,
  col2017: 114.3,
  col2018: 144.5,
  col2019: 169.9
}, {
  agrupacion: "Urbano",
  col2015: 79.6,
  col2016: 92.5,
  col2017: 62.1,
  col2018: 82.2,
  col2019: 80.6
}, {
  agrupacion: "Rural",
  col2015: 86.5,
  col2016: 63.7,
  col2017: 87.2,
  col2018: 45.7,
  col2019: 38.9
},{
  agrupacion: "Total país",
  col2015: 151,
  col2016: 184,
  col2017: 165,
  col2018: 147,
  col2019: 190
}];

This is what I get with my attempt:

[{
  agrupacion: "Total país",
  col2015: 151,
  col2016: 184,
  col2017: 165,
  col2018: 147,
  col2019: 190
}, {
  agrupacion: "Oriental",
  col2015: 78.6,
  col2016: 83.1,
  col2017: 65.6,
  col2018: 68.1,
  col2019: 63.7
}, {
  agrupacion: "Occidental",
  col2015: 177.3,
  col2016: 182.9,
  col2017: 114.3,
  col2018: 144.5,
  col2019: 169.9
}, {
  agrupacion: "Urbano",
  col2015: 79.6,
  col2016: 92.5,
  col2017: 62.1,
  col2018: 82.2,
  col2019: 80.6
}, {
  agrupacion: "Rural",
  col2015: 86.5,
  col2016: 63.7,
  col2017: 87.2,
  col2018: 45.7,
  col2019: 38.9
}]

Apparently it overwrites all the values from the first "Total país" rather than repeating that agrupacion with the new values that I added

4
  • Place this: groups.get(agrupacion)["col" + year] = +valor; within an if block with the condition that groups does not already have the agrupacion with the "col" + year prop. Then, only the first Total Pais will be stored & subsequent ones will be discarded. Commented May 23, 2022 at 18:22
  • @jsN00b I actually need it to store all of them, even if there is a second and third "Total Pais" Commented May 23, 2022 at 18:26
  • Does your data always come in fives? Commented May 23, 2022 at 18:45
  • @PeterKA sometimes it varies but if it come in fives then that means that all the elements in the current array will come like that. sometimes it comes with six values but that means that every other element will have 6 in it as well Commented May 23, 2022 at 18:47

3 Answers 3

2

Try this forEach function :

 let arrayBuild = []
      let results = []
      let currentAgrupacion = ''
      let element = {}
      
      arr.forEach(elem => {
        if(currentAgrupacion !== elem.agrupacion) {
          if(currentAgrupacion !== '') {
            results.push(element)
          }
          currentAgrupacion = elem.agrupacion
          element = {
            agrupacion: elem.agrupacion
          }
      element["col"+elem.year] = parseFloat(elem.valor)
    }
    else {
      element["col"+elem.year] = parseFloat(elem.valor)
    }
  })
  results.push(element)

  console.log(results)
Sign up to request clarification or add additional context in comments.

4 Comments

Is not working on my demo jsfiddle.net/kenpy/er3ztdnx/4
Just edited the answer. Wan't working in your fiddle cause this solution use named element in array
ty, it is working now however it has the same problem that my attempt has. It overwrites the values that I stored first and leaves only the last ones
Okay so now it won't overwrite the Total pais group but add another one
1

Reduce the array into an object where the keys correspond to the agrupacion and the values correspond to an array of objects. And the length of this array is decided based on how many times an year appears for a particular agrupacion.

So, the following array:

[
  { agrupacion: "Total país", valor: "81.8", year: 2015 },
  { agrupacion: "Total país", valor: "86.4", year: 2016 },
  { agrupacion: "Total país", valor: "67.3", year: 2015 },
  { agrupacion: "Oriental", valor: "78.6", year: 2015 },
]

Is reduced into the following object:

{
  "Total país": [
    { agrupacion: "Total país", col2015: 81.8, col2016: 86.4 },
    { agrupacion: "Total país", col2015: 67.3 },
  ],
  Oriental: [{ agrupacion: "Oriental", col2015: 78.6 }],
}

And finally we get the values of this object and flatten it to the desired result.

const arr = [
  { agrupacion: "Total país", valor: "81.8", year: 2015 },
  { agrupacion: "Total país", valor: "86.4", year: 2016 },
  { agrupacion: "Total país", valor: "67.3", year: 2017 },
  { agrupacion: "Total país", valor: "70.8", year: 2018 },
  { agrupacion: "Total país", valor: "67.6", year: 2019 },
  { agrupacion: "Oriental", valor: "78.6", year: 2015 },
  { agrupacion: "Oriental", valor: "83.1", year: 2016 },
  { agrupacion: "Oriental", valor: "65.6", year: 2017 },
  { agrupacion: "Oriental", valor: "68.1", year: 2018 },
  { agrupacion: "Oriental", valor: "63.7", year: 2019 },
  { agrupacion: "Occidental", valor: "177.3", year: 2015 },
  { agrupacion: "Occidental", valor: "182.9", year: 2016 },
  { agrupacion: "Occidental", valor: "114.3", year: 2017 },
  { agrupacion: "Occidental", valor: "144.5", year: 2018 },
  { agrupacion: "Occidental", valor: "169.9", year: 2019 },
  { agrupacion: "Urbano", valor: "79.6", year: 2015 },
  { agrupacion: "Urbano", valor: "92.5", year: 2016 },
  { agrupacion: "Urbano", valor: "62.1", year: 2017 },
  { agrupacion: "Urbano", valor: "82.2", year: 2018 },
  { agrupacion: "Urbano", valor: "80.6", year: 2019 },
  { agrupacion: "Rural", valor: "86.5", year: 2015 },
  { agrupacion: "Rural", valor: "63.7", year: 2016 },
  { agrupacion: "Rural", valor: "87.2", year: 2017 },
  { agrupacion: "Rural", valor: "45.7", year: 2018 },
  { agrupacion: "Rural", valor: "38.9", year: 2019 },
  { agrupacion: "Total país", valor: "151", year: 2015 },
  { agrupacion: "Total país", valor: "184", year: 2016 },
  { agrupacion: "Total país", valor: "165", year: 2017 },
  { agrupacion: "Total país", valor: "147", year: 2018 },
  { agrupacion: "Total país", valor: "190", year: 2019 },
];

const result = Object.values(
  arr.reduce((r, o) => {
    if (!r[o.agrupacion]) {
      r[o.agrupacion] = [{ agrupacion: o.agrupacion }];
    }
    const item = r[o.agrupacion].find((i) => !i["col" + o.year]);
    if (item) {
      item["col" + o.year] = parseFloat(o.valor);
    } else {
      r[o.agrupacion].push({
        agrupacion: o.agrupacion,
        ["col" + o.year]: parseFloat(o.valor),
      });
    }
    return r;
  }, {})
).flat();

console.log(result);

2 Comments

This one does the job, is there a way to convert the numeric string values with parseFloat() within the function?
@ChrisG Yes, I've updated my answer, please take a look!
0

You could keep track of the last yearData (the group of data you're collecting). If a given col<year> is already present within this object, create a new object.

const result = [];
let yearData;
for (const {agrupacion, valor, year} of arr) {
  const colYear = `col${year}`;
  if (!yearData || colYear in yearData) {
    yearData = { agrupacion };
    result.push(yearData);
  }
  yearData[colYear] = +valor;
}

const arr = [
  { agrupacion: "Total país", valor: "81.8",  year: 2015 },
  { agrupacion: "Total país", valor: "86.4",  year: 2016 },
  { agrupacion: "Total país", valor: "67.3",  year: 2017 },
  { agrupacion: "Total país", valor: "70.8",  year: 2018 },
  { agrupacion: "Total país", valor: "67.6",  year: 2019 },
  { agrupacion: "Oriental",   valor: "78.6",  year: 2015 },
  { agrupacion: "Oriental",   valor: "83.1",  year: 2016 },
  { agrupacion: "Oriental",   valor: "65.6",  year: 2017 },
  { agrupacion: "Oriental",   valor: "68.1",  year: 2018 },
  { agrupacion: "Oriental",   valor: "63.7",  year: 2019 },
  { agrupacion: "Occidental", valor: "177.3", year: 2015 },
  { agrupacion: "Occidental", valor: "182.9", year: 2016 },
  { agrupacion: "Occidental", valor: "114.3", year: 2017 },
  { agrupacion: "Occidental", valor: "144.5", year: 2018 },
  { agrupacion: "Occidental", valor: "169.9", year: 2019 },
  { agrupacion: "Urbano",     valor: "79.6",  year: 2015 },
  { agrupacion: "Urbano",     valor: "92.5",  year: 2016 },
  { agrupacion: "Urbano",     valor: "62.1",  year: 2017 },
  { agrupacion: "Urbano",     valor: "82.2",  year: 2018 },
  { agrupacion: "Urbano",     valor: "80.6",  year: 2019 },
  { agrupacion: "Rural",      valor: "86.5",  year: 2015 },
  { agrupacion: "Rural",      valor: "63.7",  year: 2016 },
  { agrupacion: "Rural",      valor: "87.2",  year: 2017 },
  { agrupacion: "Rural",      valor: "45.7",  year: 2018 },
  { agrupacion: "Rural",      valor: "38.9",  year: 2019 },
  { agrupacion: "Total país", valor: "151",   year: 2015 },
  { agrupacion: "Total país", valor: "184",   year: 2016 },
  { agrupacion: "Total país", valor: "165",   year: 2017 },
  { agrupacion: "Total país", valor: "147",   year: 2018 },
  { agrupacion: "Total país", valor: "190",   year: 2019 },
];

const result = [];
let yearData;
for (const { agrupacion, valor, year } of arr) {
  const colYear = `col${year}`;
  if (!yearData || colYear in yearData) {
    yearData = { agrupacion };
    result.push(yearData);
  }
  yearData[colYear] = +valor;
}

console.log(result);

The answer does assume a certain consistency in arr. Namely that each group of items share the exact same year range (2015-2019 in your data), and there are no missing years.

An example of an inconsistent input that produces a wrong output is:

const arr = [
  { agrupacion: "a", valor: "1", year: 2015 },
  { agrupacion: "a", valor: "2", year: 2016 },
  { agrupacion: "a", valor: "3", year: 2017 },
  { agrupacion: "b", valor: "4", year: 2015 },
  // 2016 missing
  { agrupacion: "b", valor: "5", year: 2017 },
  // 2015 missing
  { agrupacion: "c", valor: "6", year: 2016 },
  { agrupacion: "c", valor: "7", year: 2017 },
];

Which results in:

[
  { agrupacion: "a", col2015: 1, col2016: 2, col2017: 3 },
  { agrupacion: "b", col2015: 4, col2016: 6, col2017: 5 },
  { agrupacion: "c",                         col2017: 7 },
]

If these gaps in data can occur you'll want to change:

if (!yearData || colYear in yearData)

Into:

if (!yearData || agrupacion != yearData.agrupacion || colYear in yearData)

To ensure that a new yearData object is used if either agrupacion is different or col<year> is already present.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.