Creating a tree structure using an array of objects

I am working with an array containing the following data:

const data = [
  { id: 1, type: 'type 1' },
  { id: 2, type: 'type 2', subtype: 'subtype 2' },
  { id: 3, type: 'type 2', subtype: 'subtype 3' },
  { id: 4, type: 'type 2', subtype: 'subtype 4' },
  { id: 5, type: 'type 3', subtype: 'subtype 3' },
];

The task at hand is to create a tree structure as follows:

type 1
type 2
  subtype 2
  subtype 3
  subtype 4
type 3
  subtype 3

Answer №1

If the example data provided by the OP maintains its straightforward type/subtype structure, the approach comes down to a grouping task where the value of the type serves as the key (property name) for a new group of subtype entries (continuing the object structure) or items (shifting to an array structure).

The process of aggregating grouped data in an object aligns with a traditional reduce operation.

The following language features are utilized:

const data = [
   { id: 1, type: 'type 1' },
   { id: 2, type: 'type 2', subtype: 'subtype 2' },
   { id: 3, type: 'type 2', subtype: 'subtype 3' },
   { id: 4, type: 'type 2', subtype: 'subtype 4' },
   { id: 5, type: 'type 3', subtype: 'subtype 3' },
];
console.log(
  'pure object based tree ...',
  data
    .reduce((result, { type, subtype = null }) => {

      const typeGroup = (result[type] ??= {});

      if (subtype !== null) {
        typeGroup[subtype] = {};
      }
      return result;

    }, {})
)
console.log(
  'object and array item based tree ...',
  data
    .reduce((result, { type, subtype = null }) => {

      const groupedSubtypeList = (result[type] ??= []);

      if (subtype !== null) {
        groupedSubtypeList.push(subtype);
      }
      return result;

    }, {})
)
console.log(
  'what the OP probably is looking for ...',
  Object
    .entries(
      // same reduce functionality as one example before.
      data
        .reduce((result, { type, subtype = null }) => {

          const groupedSubtypeList = (result[type] ??= []);

          if (subtype !== null) {
            groupedSubtypeList.push(subtype);
          }
          return result;

        }, {})
    )
    // additional mapping over the reduce result's entries.
    .map(([type, subtypes]) => {
      const typeItem = {
        type: type.replace('type', '').trim(),
      };
      if (subtypes.length >= 1) {
        typeItem.subtypes = subtypes
          .map(subtype => ({
            subtype: subtype.replace('subtype', '').trim(),
          }));
      }
      return typeItem;
    })
)
.as-console-wrapper { min-height: 100%!important; top: 0; }

Answer №2

Edit 2 - revised for better organization

const data = [{
    id: 1,
    type: 'type 1'
  },
  {
    id: 2,
    type: 'type 2',
    subtype: 'subtype 2'
  },
  {
    id: 3,
    type: 'type 2',
    subtype: 'subtype 3'
  },
  {
    id: 4,
    type: 'type 2',
    subtype: 'subtype 4'
  },
  {
    id: 5,
    type: 'type 3',
    subtype: 'subtype 3'
  },
];

var pretype = "";
//const newArr = data.map(change);

var pretype = "";
var preindex = -1;
const arr2 = []


data.forEach(function(idx) {
  if (pretype != idx.type) {
    //console.log(idx.type);
    arr2.push({
      //'id': idx.id,
      "type": idx.type.replace("type ", "")
    });

    preindex++;
  }

  if (idx.subtype) {
    //console.log("pr", preindex, arr2[preindex], arr2[preindex]["subtypes"])
    if (arr2[preindex]["subtypes"] == undefined)
      arr2[preindex]["subtypes"] = [];

    arr2[preindex]["subtypes"].push({
      "subtype": idx.subtype.replace("subtype ", "")
    })
  }
  pretype = idx.type;


});
console.log("arr2: ",arr2)
console.log("flat: ",JSON.stringify(arr2));

function change(id) {
  if (pretype != id.type)
    console.log(id.type);
  if (id.subtype)
    console.log(id.subtype)
  
  pretype = id.type;

}

Answer №3

Create a tree structure from an array, merging values with the same keys

const data = [
  { id: 1, type: "type 1" },
  { id: 2, type: "type 2", subtype: "subtype 2" },
  { id: 3, type: "type 2", subtype: "subtype 3" },
  { id: 4, type: "type 2", subtype: "subtype 4" },
  { id: 5, type: "type 3", subtype: "subtype 3" },
];

const buildTreeStructure = (arr) => {
  const obj = {};
  arr.forEach((item) => {
    if (obj[item.type]) {
      obj[item.type].subs.push(item.subtype);
    } else {
      obj[item.type] = {
        type: item.type,
        subs: item.subtype ? [item.subtype] : [],
      };
    }
  });
  return Object.values(obj);
};

console.log(buildTreeStructure(data));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Universal form submission via ajax

Issue with ajax/javascript: I am working on an application that includes multiple forms. My goal is to create a generic JavaScript function that can submit forms to their respective controllers by using the form ID. I have successfully retrieved the form I ...

Performing multiple requests using Axios library in a React application

My goal is to make 2 requests and define variables using this.setState({}) for future modifications. This is the code snippet I have: class App extends React.Component { constructor() { super(); this.state = {user: false, repository :false} ...

After resizing, reordering, hiding, or showing columns in the kendo grid, the grid's data source will be set to

I am encountering an issue with my kendo grid where the data disappears after performing certain actions: Reordering columns using mouse drag and drop Resizing columns using mouse drag and drop Hiding columns through the column menu Showing columns throu ...

What is the best way to ensure that the bootstrap nav tab content fits perfectly on one line?

Check out this bootstrap navbar example You can see a screenshot here. <ul class="nav nav-tabs" style="display: inlne-block"> <li class="nav-item" style="text-align: center; display: inline;"> <div> <a class="nav ...

What steps should I take to ensure that this JSON.stringify function functions as intended?

I'm facing a minor challenge in formatting my arrays into the desired JSON structure. Here's the code I've used: var arrData = [{label:Test,value:199.12}, {label:Test2,value:1024}] var data = []; for (var i = 0; i < arrData.length ...

The Ajax GIF Loader is not functioning in the latest versions of Internet Explorer and Firefox, but it is running smoothly in

The animated GIF loader functions correctly in the latest version of Chrome, but does not animate when viewed in IE and Firefox. Below is the code snippet: $("#DIALOG").dialog({ buttons : { "Yes" : function() { ...

Issue: Module '/Users/MYNAME/Desktop/Projects/MYPROJECTNAME' not found

I am currently in the process of compiling Node using TypeScript, and I'm still getting acquainted with it. An issue I encountered was that my /src files were not being updated when I made changes and restarted the server. To troubleshoot, I decided ...

Issue with ng-repeat not updating in Meteor and Angular collaboration

(This is not one of those "Oh I forgot $scope.$apply()" problems) Question is: How can I achieve live binding with ng-repeat and a reactive helper function in the controller? Let's focus on the code: index.js: <body ng-controller="AppCtrl as ap ...

There are no documents found with the specified UUID in MongoDB

I have been attempting to retrieve a specific document from MongoDB that includes the field "ownerId" containing a binary UUID. In the Mongo console, when I run the command db.dataset.find({ownerId: BinData(3,"ZQ6EAOKbQdSnFkRmVUUAAA==")}).pretty() The ou ...

I developed a digital Magic 8 Ball program, but unfortunately, it's only providing me with one response

I'm currently working on a Discord Bot for my friends and myself. One of the scripts I've created is an 8Ball script, but it's only giving me one answer. Here's the code snippet for my variable: var rand = ['Yes', 'No&apo ...

What is the best way to take control of DOM alterations?

In the project I'm currently working on, the client has a modal box with its display property set to none. Upon clicking the CTA button, it triggers the application of the fadein and fadeout classes. This results in a change from display:none to displ ...

Getting data from a PHP request using AngularJS can be achieved by creating an HTTP request in

I am trying to send a basic REST service request using Angular for the PHP code below. Unfortunately, the request is resulting in an error. Check out the live code here PHP Code <?php /* Simple array */ $json = array("status" => 0, "msg" => ...

Adding a byte in between two bytes may be required when transmitting a byte array via an HTTP connection

Currently, I am in the process of establishing communication between an ESP and a nodejs server by sending data in bytes back and forth. However, I am facing an issue where when I send these 3 bytes in sequence over http, an additional byte is being added ...

Dreamweaver restricts my ability to utilize JavaScript for coding

My JavaScript isn't working in Dreamweaver. I have linked the script file correctly using the given code: <script src="file:///C:/Users/Matthew/Desktop/Untitled-2.js" type="text/script"></script> However, when I try to call it with scrip ...

Can two writable stores in Svelte be set up to subscribe to each other simultaneously?

There is a unique scenario where two objects share data, yet have different structures. For instance, the 'Team' object has the team ID as its key. The 'Team' object includes 'name' and 'users' objects as its values ...

Dynamically Remove One Form from a Django Formset

I have been using the following code to dynamically add a form to my formset: .html {{ form2.management_form }} <div id="form_set"> {% for form2 in form2.forms %} <table class="table table2" width=100%> ...

Error in Postman: Express and Mongoose throwing 'name' property as undefined

While trying to create and insert 'user' JSON documents according to the model below, upon sending a POST request to localhost:3000/api/student, I encountered an error using Postman: TypeError: Cannot read property 'name' of undefined ...

What is the reason for the result of .splice being a singular object?

I've been working on updating my API and I've run into a problem. I need to replace the first element in an array like so: Given the data: const data = ["1", 2, 3, 4, 5, 6] I want the output to be: ["New_text", 2, 3, 4, 5] I attempted to use t ...

Prevent certain dates from being selected in a designated input field

I am facing an issue with disabling certain array dates for a specific input field in a datepicker calendar. Even though I have included the script to exclude those dates, they are not getting disabled for that particular input field. html <input cla ...

Tips for transferring objects between AngularJS directives

Is it possible to access an object named foo that is defined/instantiated inside the link function of directive A from the link function of another separate directive? ...