skip to Main Content

I have an array of objects and I´d like to transsform it in a other.

I can do it with a for loop, but I´d like to use reduce.
How could I do it using reduce?

const arr=[
  { medico: "med1", rateio: "rat1", convenio: "conv1", subtotal: 10 },
  { medico: "med2", rateio: "rat2", convenio: "conv2", subtotal: 10 },
  { medico: "med2", rateio: "rat2", convenio: "conv2", subtotal: 20 },
  { medico: "med1", rateio: "rat1", convenio: "conv3", subtotal: 20 },
  { medico: "med1", rateio: "rat1", convenio: "conv3", subtotal: 25 },
  { medico: "med2", rateio: "rat3", convenio: "conv4", subtotal: 15 },
  { medico: 'med2', rateio: 'rat4', convenio: 'conv3', subtotal: 10 },
];

I need the next result:

const result=[
  {medico: "med1", grantotals:[
    {
      rateio: "rat1",
      grandtotals: [
        { convenio: "conv1", sum_subtotal: 10 },
        { convenio: "conv3", sum_subtotal: 45 }
      ]
    }
  ]},
  {medico: "med2", grantotals:[
      {
        rateio: "rat2",
        grandtotals: [
          { convenio: "conv2", sum_subtotal: 30 },
        ]
      },
      {
        rateio: "rat3",
        grandtotals: [
          { convenio: "conv4", sum_subtotal: 15 },
        ]
      },
      {
        rateio: "rat4",
        grandtotals: [
          { convenio: "conv3", sum_subtotal: 10 },
        ]
      }
    ]}
    ]

3

Answers


  1. Using the reduce() method in JavaScript, Here below I demonstrate how to apply reduce() to convert the arr array into the desired result array structure:

    1. The reduce() method is used to iterate over the arr array and transform the data into the desired structure.
    2. For each object (obj) in the arr array. We check if there is an existing medico object in the acc array using the find() method.
    3. If an existing medico object is found, we continue searching for the existing rateio object within that medico object.
    4. If an existing rateio object is found, we continue searching for the existing convenio object within that rateio object.
    5. If an existing convenio object is found, we update the sum_subtotal property by adding the subtotal value to it.
    6. If an existing convenio object is not found, we create a new convenio object and push it into the grandtotals array within the existing rateio object.
    7. If an existing rateio object is not found, we create a new rateio object with the corresponding convenio object and push it into the grantotals array within the existing medico object.
    8. If an existing medico object is not found, we create a new medico object with the corresponding rateio and convenio objects and push it into the acc array.
    9. Finally, the transformed acc array is returned as the result array. Is there anything else I can help you with?
    const arr = [
        { medico: "med1", rateio: "rat1", convenio: "conv1", subtotal: 10 },
        { medico: "med2", rateio: "rat2", convenio: "conv2", subtotal: 10 },
        { medico: "med2", rateio: "rat2", convenio: "conv2", subtotal: 20 },
        { medico: "med1", rateio: "rat1", convenio: "conv3", subtotal: 20 },
        { medico: "med1", rateio: "rat1", convenio: "conv3", subtotal: 25 },
        { medico: "med2", rateio: "rat3", convenio: "conv4", subtotal: 15 },
        { medico: "med2", rateio: "rat4", convenio: "conv3", subtotal: 10 },
      ];
      
      const result = arr.reduce((acc, obj) => {
        const existingMedico = acc.find((item) => item.medico === obj.medico);
      
        if (existingMedico) {
          const existingRateio = existingMedico.grantotals.find(
            (item) => item.rateio === obj.rateio
          );
      
          if (existingRateio) {
            const existingConvenio = existingRateio.grandtotals.find(
              (item) => item.convenio === obj.convenio
            );
      
            if (existingConvenio) {
              existingConvenio.sum_subtotal += obj.subtotal;
            } else {
              existingRateio.grandtotals.push({
                convenio: obj.convenio,
                sum_subtotal: obj.subtotal,
              });
            }
          } else {
            existingMedico.grantotals.push({
              rateio: obj.rateio,
              grandtotals: [
                {
                  convenio: obj.convenio,
                  sum_subtotal: obj.subtotal,
                },
              ],
            });
          }
        } else {
          acc.push({
            medico: obj.medico,
            grantotals: [
              {
                rateio: obj.rateio,
                grandtotals: [
                  {
                    convenio: obj.convenio,
                    sum_subtotal: obj.subtotal,
                  },
                ],
              },
            ],
          });
        }
      
        return acc;
      }, []);
      
      console.log(result)
      
    Login or Signup to reply.
  2. One approach is to fold your input into a format like this, using reduce:

    {
        med1: {
            rat1: {conv1: 10, conv3: 45}
        },
        med2: {
            rat2: {conv2: 30},
            rat3: {conv4: 15},
            rat4: {conv3: 10}
        }
    }
    

    and rehydrating with your property names, by repeatedly using Object.entries and mapping the results. It turns out relatively straightforward:

    const restructure = (xs) => {
      const compressed = xs.reduce((a, {medico, rateio, convenio, subtotal}) => {
        a[medico] ||= {}
        a[medico][rateio] ||= {}
        a[medico][rateio][convenio] ||= 0
          a[medico][rateio][convenio] += subtotal
        return a
      }, {})
      return Object.entries(compressed).map(([medico, grantotals]) => ({
        medico, 
        grantotals: Object.entries(grantotals).map(([rateio, grandtotals]) => ({
          rateio, 
          grandtotals: Object.entries(grandtotals).map(([convenio, sum_subtotal]) => ({
            convenio, 
            sum_subtotal
          })) 
      }))
    }))}
    
    const arr = [{medico: "med1", rateio: "rat1", convenio: "conv1", subtotal: 10}, {medico: "med2", rateio: "rat2", convenio: "conv2", subtotal: 10}, {medico: "med2", rateio: "rat2", convenio: "conv2", subtotal: 20}, {medico: "med1", rateio: "rat1", convenio: "conv3", subtotal: 20}, {medico: "med1", rateio: "rat1", convenio: "conv3", subtotal: 25}, {medico: "med2", rateio: "rat3", convenio: "conv4", subtotal: 15}, {medico: 'med2', rateio: 'rat4', convenio: 'conv3', subtotal: 10}]
    
    console.log(restructure(arr))
    .as-console-wrapper {max-height: 100% !important; top: 0}

    compressed is the format above, which we create by what is essentially a nested groupBy function. Then we return an object which works its way inward along the nested properties, using Object.entries to create the key-value pairs, and mapping those to simple objects.

    Login or Signup to reply.
  3. Added an explanation in the comments:

    const arr = [
      { medico: "med1", rateio: "rat1", convenio: "conv1", subtotal: 10 },
      { medico: "med2", rateio: "rat2", convenio: "conv2", subtotal: 10 },
      { medico: "med2", rateio: "rat2", convenio: "conv2", subtotal: 20 },
      { medico: "med1", rateio: "rat1", convenio: "conv3", subtotal: 20 },
      { medico: "med1", rateio: "rat1", convenio: "conv3", subtotal: 25 },
      { medico: "med2", rateio: "rat3", convenio: "conv4", subtotal: 15 },
      { medico: 'med2', rateio: 'rat4', convenio: 'conv3', subtotal: 10 },
    ];
    
    const result = arr.reduce((prev, current) => {
      const { medico, rateio, convenio, subtotal } = current;
      /* Searching medico */
      const medicoIndex = prev.findIndex(o => o.medico === medico);
      /* If medico doesn't exists */
      if (medicoIndex < 0) {
        prev.push({
          medico: medico,
          grandtotals: [{
            rateio: rateio,
            grandtotals: [
              {
                convenio: convenio,
                subtotal: subtotal
              }
            ]
          }]
        })
      } else {
        const medicoValut = prev[medicoIndex];
        /* Searching rateio */
        const rateioIndex = medicoValut.grandtotals.findIndex(o => o.rateio === rateio);
        /* If rateio doesn't exists */
        if (rateioIndex < 0) {
          medicoValut.grandtotals.push({
            rateio: rateio,
            grandtotals: [{
              convenio: convenio,
              subtotal: subtotal,
            }]
          })
        } else {
          const convenioValue = medicoValut.grandtotals[rateioIndex];
          /* Searching convenio */
          const convenioIndex = convenioValue.grandtotals.findIndex(o => o.convenio === convenio);
          /* If convenio doesn't exists */
          if (convenioIndex < 0){
            convenioValue.grandtotals.push({
              convenio: convenio,
              subtotal: subtotal,
            })
          }else{
            /* Else add subtotal */
            convenioValue.grandtotals[convenioIndex].subtotal += subtotal;
          }
        }
      }
      return prev;
    }, []);
    
    console.log(JSON.stringify(result, null, 2));
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search