javascriptecmascript-6treehierarchytreetable

Convert flat data to 3 level hierarchy/tree


I'm currently converting my flat data to a hierarchy with 2 levels, but I now need to add an additional 3rd level to this data. I haven't been able to figure out how to modify by existing method so far. I'm open to completely new methods also.

Here is the code I'm currently using to do the conversion:

        chartdata = sfdata.data.reduce((acc, {
            items: [cat, val, salesTY, salesLY, unitsTY, unitsLY]
        }) => {
            acc[cat] = acc[cat] || [];
            acc[cat].push({
                name: val,
                salesTY: salesTY,
                salesLY: salesLY,
                unitsTY: unitsTY,
                unitsLY: unitsLY
            });
            return acc;
        }, {});

        // Generate desired output structure.
        chartdata = Object.entries(chartdata).map(([k, v]) => ({
            category: k,
            children: v
        }));

It maps to the different categories and then converts that map to a category>children structure

And here is the fiddle where I'm using this tree structure: http://jsfiddle.net/zt4nhxcw/3/

I've started a new fiddle here with the new Brand data included: http://jsfiddle.net/t1uz85b2/

The goal is to add a 3rd level. So every child at the 2nd level would have Brand underneath of them.

Here is a very small snippet of how the data comes in:

[
  {
    "items": [
      "SSD",
      "PBNA",
      "MOUNTAIN DEW",
      851255.3500000001,
      672407.8399999997,
      782364.9999999991,
      641579.0000000006
    ],
    "hints": {
      "index": 0
    }
  },
  {
    "items": [
      "Energy",
      "RED BULL NORTH AMERICA",
      "RED BULL",
      836632.2299999997,
      654021.2899999995,
      267216,
      214321.00000000015
    ],
    "hints": {
      "index": 1
    }
  },
  {
    "items": [
      "SSD",
      "PBNA",
      "PEPSI",
      478704.02999999974,
      392746.69999999995,
      533557.0000000006,
      457008.0000000001
    ],
    "hints": {
      "index": 4
    }
  },
  {
    "items": [
      "Energy",
      "RED BULL NORTH AMERICA",
      "RED BULL EDITIONS",
      449618.55000000016,
      328150.8999999997,
      162428.9999999999,
      117521.00000000001
    ],
    "hints": {
      "index": 5
    }
  },
  {
    "items": [
      "SSD",
      "CCNA",
      "COKE",
      349685.7899999996,
      276766.95,
      445485.0000000002,
      351214.0000000003
    ],
    "hints": {
      "index": 9
    }
  }
]

And here is the final structure I'm trying to achieve:

[
  {
    "category": "SSD",
    "children": [
      {
        "brand": "PBNA",
        "children": [
          {
            "name": "MOUNTAIN DEW",
            "salesTY": 851255.3500000001,
            "salesLY": 672407.8399999997,
            "unitsTY": 782364.9999999991,
            "unitsLY": 641579.0000000006
          }
        ]
      },
      {
        "brand": "CCNA",
        "children": [
          {
            "name": "COKE",
            "salesTY": 349685.7899999996,
            "salesLY": 276766.95,
            "unitsTY": 445485.0000000002,
            "unitsLY": 351214.0000000003
          }
        ]
      }
    ]
  },
  {
    "category": "Energy",
    "children": [
      {
        "brand": "RED BULL NORTH AMERICA",
        "children": [
          {
            "name": "RED BULL",
            "salesTY": 836632.2299999997,
            "salesLY": 654021.2899999995,
            "unitsTY": 267216,
            "unitsLY": 214321.00000000015
          },
          {
            "name": "RED BULL EDITIONS",
            "salesTY": 449618.55000000016,
            "salesLY": 328150.8999999997,
            "unitsTY": 162428.9999999999,
            "unitsLY": 117521.00000000001
          }
        ]
      }
    ]
  }
]

Solution

  • You could take a dynamic approach and take an array with the keys for all values and a limit of the wanted depth.

    const
        data = [{ items: ["SSD", "PBNA", "MOUNTAIN DEW", 851255.3500000001, 672407.8399999997, 782364.9999999991, 641579.0000000006], hints: { index: 0 } }, { items: ["Energy", "RED BULL NORTH AMERICA", "RED BULL", 836632.2299999997, 654021.2899999995, 267216, 214321.00000000015], hints: { index: 1 } }, { items: ["SSD", "PBNA", "PEPSI", 478704.02999999974, 392746.69999999995, 533557.0000000006, 457008.0000000001], hints: { index: 4 } }, { items: ["Energy", "RED BULL NORTH AMERICA", "RED BULL EDITIONS", 449618.55000000016, 328150.8999999997, 162428.9999999999, 117521.00000000001], hints: { index: 5 } }, { items: ["SSD", "CCNA", "COKE", 349685.7899999996, 276766.95, 445485.0000000002, 351214.0000000003], hints: { index: 9 } }],
        keys = ['category', 'brand', 'name', 'salesTY', 'salesLY', 'unitsTY', 'unitsLY'],
        limit = 2,
        result = data
            .reduce((temp, { items }) => {
                keys
                    .slice(0, limit)
                    .reduce(function (r, k, i) {
                        if (!r[items[i]]) {
                            r[items[i]] = { _: [] };
                            r._.push({ [k]: items[i], children: r[items[i]]._ });
                        }
                        return r[items[i]];
                    }, temp)
                    ._
                    .push(keys
                        .slice(limit)
                        .reduce((o, k, i) => (o[k] = items[i + limit], o), {})
                    );
                return temp;
            }, { _: [] })
            ._;
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }