Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

358
Visualizações
JS - How to transform an array of objects into different groups based off property value, further segregate data, and aggregating some of the data

Let' say I have an array of objects like this:

[
    {
    "transactiondate.Display.V1.FormattedValue": "2/1/2016",
    "transactiondate": "2016-02-01T08:00:00Z",
    "level": "level 1",
    "amount": "5"
    },
    {
    "transactiondate.Display.V1.FormattedValue": "2/1/2017",
    "transactiondate": "2017-02-01T08:00:00Z",
    "level": "level 1",
    "amount": "7"
    },
    {
    "transactiondate.Display.V1.FormattedValue": "2/1/2017",
    "transactiondate": "2017-02-01T08:00:00Z",
    "level": "level 1",
    "amount": "4"
    },
    {
    "transactiondate.Display.V1.FormattedValue": "2/1/2016",
    "transactiondate": "2016-02-01T08:00:00Z",
    "level": "level 2",
    "amount": "10"
    },
    {
    "transactiondate.Display.V1.FormattedValue": "2/1/2016",
    "transactiondate": "2016-02-01T08:00:00Z",
    "level": "level 2",
    "amount": "20"
    },
    {
    "transactiondate.Display.V1.FormattedValue": "2/1/2017",
    "transactiondate": "2017-02-01T08:00:00Z",
    "level": "level 2",
    "amount": "50"
    },
    ...
]

I want the output to look like this:

[
    {
        name: "level 1",
        data: [5, 11] // Total amount in order of ascending year. 2016 had total amount of 5 and 2017 had total amount of 11
    },
    {
        name: "level 2",
        data: [30, 50]
    },
    {
        name: "level x",
        data: [...]
    }
]

I was able to successfully group it by year by doing the following but I'm not quite sure how to go about taking the resulting object then transforming it into the desired output. I would have to loop through entries of the object, split it up into groups by "level", iterate through the entries again then use reduces to accumulate the amounts, then split them up again into "name" and "data" key/value pairs? I feel like that is very inefficient if I can even get that to work. Any help would be much appreciated.

var groupedByYr = data.reduce(function (r, a) {
                r[a.transactiondate.substring(0,4)] = r[a.transactiondate.substring(0,4)] || [];
                r[a.transactiondate.substring(0,4)].push(a);
                return r;
            });
about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

maybe not the perfect answer but it has a 1 loop I guess :D

I tried to explain it in the code as much as I could

var data = [{
      "transactiondate.Display.V1.FormattedValue": "2/1/2016",
      "transactiondate": "2016-02-01T08:00:00Z",
      "level": "level 1",
      "amount": "5"
    },
    {
      "transactiondate.Display.V1.FormattedValue": "2/1/2017",
      "transactiondate": "2017-02-01T08:00:00Z",
      "level": "level 1",
      "amount": "7"
    },
    {
      "transactiondate.Display.V1.FormattedValue": "2/1/2017",
      "transactiondate": "2017-02-01T08:00:00Z",
      "level": "level 1",
      "amount": "4"
    },
    {
      "transactiondate.Display.V1.FormattedValue": "2/1/2016",
      "transactiondate": "2016-02-01T08:00:00Z",
      "level": "level 2",
      "amount": "10"
    },
    {
      "transactiondate.Display.V1.FormattedValue": "2/1/2016",
      "transactiondate": "2016-02-01T08:00:00Z",
      "level": "level 2",
      "amount": "20"
    },
    {
      "transactiondate.Display.V1.FormattedValue": "2/1/2017",
      "transactiondate": "2017-02-01T08:00:00Z",
      "level": "level 2",
      "amount": "50"
    },
  ],
  parse = [] //save parse array,
  levels = {} //save level keys;
data.map((item) => {
  let map = new Map(); // create a map for location of the value of the each year
  if (typeof levels[item.level] == 'undefined') { // we didn't parse the level yet so it's new
    map.set(item.transactiondate.substring(0, 4), 0); // set the location of the amount of the first year as 0 because it's the first
    let key = parse.push({
      name: item.level,
      yearindexes: map,
      data: [parseInt(item.amount)]
    }); // save the parse array size as level key
    levels[item.level] = key - 1;  // save the level and index of it (key -1) 
  } else {
   // parse the level before so it's exists
    if (parse[levels[item.level]].yearindexes.has(item.transactiondate.substring(0, 4))) { // we have the year in the data
    let yearindex = parse[levels[item.level]].yearindexes.get(item.transactiondate.substring(0, 4)); // get the index of the year
      parse[levels[item.level]].data[yearindex] += parseInt(item.amount); // add the amount of the year to the index
    } else {
      // it's a new years
      parse[levels[item.level]].data.push(parseInt(item.amount));// push the new year amount to the data
      map = parse[levels[item.level]].yearindexes; // get previes year indexes
      map.set(item.transactiondate.substring(0, 4), map.size); // add the new year with the size of yearindexes as the index of the new year
      parse[levels[item.level]].yearindexes = map; // set the new yearindexes
    }
  }
});
//remove yearindexes from parse (optional)
const result = parse.map(({yearindexes,...rest}) => ({...rest}));
console.log(result);

about 4 years ago · Juan Pablo Isaza Relatório

0

I think you're just going to have to do it in two passes, one with forEach to get everything into a buffer, and one with map to take that buffer and format it how you like. I think you can do it in one pass, but it is going to be a lot easier to read if you don't.

Here I use forEach to loop over the data elements, and I use an object buffer. Since it's an object, I can use keys to keep the entries unique, and keep adding the amounts for each year using the year as a subkey (which I get from Date's getYear()). The first time you hit each key, you will either need to check for its existence in the target object OR you can do what I did, null coalesce to a default value (either an empty object or 0).

Then when the buffer is built, I use Object.values to map the object to an array and also to convert the amounts objects to arrays.

Let me know if I got that right.

const data = [
    {
    "transactiondate.Display.V1.FormattedValue": "2/1/2016",
    "transactiondate": "2016-02-01T08:00:00Z",
    "level": "level 1",
    "amount": "5"
    },
    {
    "transactiondate.Display.V1.FormattedValue": "2/1/2017",
    "transactiondate": "2017-02-01T08:00:00Z",
    "level": "level 1",
    "amount": "7"
    },
    {
    "transactiondate.Display.V1.FormattedValue": "2/1/2017",
    "transactiondate": "2017-02-01T08:00:00Z",
    "level": "level 1",
    "amount": "4"
    },
    {
    "transactiondate.Display.V1.FormattedValue": "2/1/2016",
    "transactiondate": "2016-02-01T08:00:00Z",
    "level": "level 2",
    "amount": "10"
    },
    {
    "transactiondate.Display.V1.FormattedValue": "2/1/2016",
    "transactiondate": "2016-02-01T08:00:00Z",
    "level": "level 2",
    "amount": "20"
    },
    {
    "transactiondate.Display.V1.FormattedValue": "2/1/2017",
    "transactiondate": "2017-02-01T08:00:00Z",
    "level": "level 2",
    "amount": "50"
    }
];


let buffer = {};
data.forEach(i=>{
  let t = new Date(i.transactiondate).getYear();
  let amts = buffer[i.level]?.amts || {};
  amts[t] = i.amount*1 + (amts[t] || 0);
  buffer[i.level] = {name: i.level, amts: amts};
});

//console.log(buffer);
let final = Object.values(buffer).map(m=>{
  return {name: m.name, data: Object.values(m.amts)};
});

console.log(final);

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda