Home > Net >  Sum children and acumulate with parents array tree Angular Typescript
Sum children and acumulate with parents array tree Angular Typescript

Time:03-17

enter image description here

Im working on Angular 11 project i need show a tree view with an input by row, the user can change values of input and i need recalculate totals for every change on input. I want to calculate the sum of the child nodes and save that on parent node for show the new totals.

This is the dataStructure and expected results on "total" key

dataTreeView =  [
      {
        "account_id": "42",
        "account_parent": null,
        "name": "Ingresos de actividades ordinarias",
        "total": 17, // expected result sum 5   12 = 17
        "children": [
          {
            "account_id": "422",
            "account_parent": "42",
            "name": "Ventas",
            "total": 5
          },
          {
            "account_id": "421",
            "account_parent": "42",
            "name": "Devoluciones en ventas",
            "total": 12
          }
        ]
      },
      {
        "account_id": "55",
        "account_parent": null,
        "name": "Costos de ventas y operación",
        "total": 24, // expected result 19   5
        "children": [
          {
            "account_id": "552",
            "account_parent": "55",
            "name": "Costos de la mercancía vendida",
            "total": 19, // expected result sum 5   14 = 19
            "children": [
              {
                "account_id": "5524",
                "account_parent": "552",
                "name": "Devoluciones en compras de inventario",
                "total": 14, // expected result sum 4   10 = 14
                "children": [
                  {
                    "account_id": "55241",
                    "account_parent": "5524",
                    "name": "Descuentos",
                    "total": 10
                  },
                  {
                    "account_id": "55242",
                    "account_parent": "5524",
                    "name": "Otros",
                    "total": 4
                  },
                ]
              },
              {
                "account_id": "5523",
                "account_parent": "552",
                "name": "Costos del inventario",
                "total": 5
              },
            ]
          },
        ]
      }
    ]

I try with reduce but not working

data.reduce(function x(r, a) {
 a.total = a.total || (Array.isArray(a.children) && 
 a.children.reduce(x, 0)) || 0;
 return r   a.total;
}, 0)

I appreciate your help with this solution

Thanks and regards

CodePudding user response:

If you have values for total and other nested value which sums to a new value, you could move o.total to the end of the expression and evaluate the array first.

const
    updateTotal = (r, o) => r   (
        o.total = (o.children || []).reduce(updateTotal, 0) || o.total || 0
    ),
    data = [{ account_id: "42", account_parent: null, name: "Ingresos de actividades ordinarias", total: 10, children: [{ account_id: "422", account_parent: "42", name: "Ventas", total: 5 }, { account_id: "421", account_parent: "42", name: "Devoluciones en ventas", total: 12 }] }, { account_id: "55", account_parent: null, name: "Costos de ventas y operación", total: 0, children: [{ account_id: "552", account_parent: "55", name: "Costos de la mercancía vendida", total: 0, children: [{ account_id: "5524", account_parent: "552", name: "Devoluciones en compras de inventario", total: 0, children: [{ account_id: "55241", account_parent: "5524", name: "Descuentos", total: 10 }, { account_id: "55242", account_parent: "5524", name: "Otros", total: 4 }] }, { account_id: "5523", account_parent: "552", name: "Costos del inventario", total: 5 }] }] }];

data.reduce(updateTotal, 0);

console.log(data)
.as-console-wrapper { max-height: 100% !important; top: 0; }

CodePudding user response:

For each element of your array you want to set the value total that is the sum of all total inside children, right?

data.forEach(el => {
  el.total = el.total   el.children.reduce((a,b) => a.total   b.total);
}

CodePudding user response:

You need a recursive function to traverse your tree

const data = [
  {
    "account_id": "42",
    "account_parent": null,
    "name": "Ingresos de actividades ordinarias",
    "children": [
      {
        "account_id": "422",
        "account_parent": "42",
        "name": "Ventas",
        "total": 5
      },
      {
        "account_id": "421",
        "account_parent": "42",
        "name": "Devoluciones en ventas",
        "total": 12
      }
    ]
  },
  {
    "account_id": "55",
    "account_parent": null,
    "name": "Costos de ventas y operación",
    "children": [
      {
        "account_id": "552",
        "account_parent": "55",
        "name": "Costos de la mercancía vendida",
        "children": [
          {
            "account_id": "5524",
            "account_parent": "552",
            "name": "Devoluciones en compras de inventario",
            "children": [
              {
                "account_id": "55241",
                "account_parent": "5524",
                "name": "Descuentos",
                "total": 10
              },
              {
                "account_id": "55242",
                "account_parent": "5524",
                "name": "Otros",
                "total": 4
              },
            ]
          },
          {
            "account_id": "5523",
            "account_parent": "552",
            "name": "Costos del inventario",
            "total": 5
          },
        ]
      },
    ]
  }
]

function addTotalFromChildren(arr){ //Important function
  arr.forEach(obj => { //For each element of the array
    if("children" in obj) { //Check if element has children
      addTotalFromChildren(obj.children) //Then, we need to calculate the add total for those children
      obj.total = obj.children.reduce((a, v) => a  = v.total, 0) //then we calculate the sum of those total
    } //Else it already has a total property
  })
}
addTotalFromChildren(data)
console.log(data)

I added some comments to explain the code.

Let me know if you don't understand something in the comments below.

  • Related