Transforming a flat TypeScript array into a nested object structure

I'm working on implementing a user interface to offer a comprehensive overview of our LDAP branches. To achieve this, I plan to utilize Angular Materials Tree as it provides a smooth and intuitive browsing experience through all the branches (https://material.angular.io/components/tree/overview)

My Current Setup:

I have an array containing multiple LDAP paths represented as strings:

groups = [
     'cn=devops,ou=smallUnit1,ou=unit1,o=group1,c=de',
     'cn=devops,ou=smallUnit1,ou=unit1,o=group2,c=de',        
     'cn=devops,ou=smallUnit2,ou=unit1,o=group1,c=de',
     'cn=dev,ou=smallUnit1,ou=unit2,o=group1,c=de',
     'cn=dev,ou=smallUnit1,ou=unit1,o=group2,c=de',
     'cn=ops,ou=smallUnit1,ou=unit1,o=group1,c=de'
]

Progress So Far:

I've transformed these strings into arrays of standalone paths with dependencies. For example, here's the breakdown for groups[0]:

dependencies = [
   {id: 'c=de',          parent: NULL,            child: 'o=group1'},
   {id: 'o=group1',      parent: 'c=de',          child: 'ou=unit1'},
   {id: 'ou=unit1',      parent: 'o=group1',      child: 'ou=smallUnit1'},
   {id: 'ou=smallUnit1', parent: 'ou=unit1',      child: 'cn=devops'},
   {id: 'cn=devops',     parent: 'ou=smallUnit1', child: NULL}

]

Next Steps:

I require an object where keys represent paths in our LDAP structure:

{
   c=de: {
       o=group1: {
          ou=unit1: {
             ou=smallUnit1: {
                cn=devops: {},
                cn=ops: {}
             },
             ou=smallUnit2: {
                cn=devops: {}
             }
          },
          ou=unit2: {
             ou=smallUnit1: {
                cn=dev: {}
             }
          }
       },
       o=group2: {
          ou=unit1: {
             ou=smallUnit1: {
                cn=devops: {},
                cn=dev: {}
             }
          }
       }
   }
} 

I've attempted to implement methods similar to those discussed here: Build tree array from flat array in javascript However, the algorithm uses push functions to add new branches which doesn't align with my requirement of having keys as nested objects.

Answer №1

If you look closely, you'll notice that using groups directly is the way to go because all necessary information is already in reverse order and there's no need for dependencies.

Here's what you should do:

  • Go through each element of groups
  • Break down the strings within groups
  • Use the values on the right side as keys for an object and return the inner object at each step.

var groups = ['cn=devops,ou=smallUnit1,ou=unit1,o=group1,c=de', 'cn=devops,ou=smallUnit1,ou=unit1,o=group2,c=de', 'cn=devops,ou=smallUnit2,ou=unit1,o=group1,c=de', 'cn=dev,ou=smallUnit1,ou=unit2,o=group1,c=de', 'cn=dev,ou=smallUnit1,ou=unit1,o=group2,c=de', 'cn=ops,ou=smallUnit1,ou=unit1,o=group1,c=de'],
    tree = groups.reduce((object, string) => {
        string
            .split(',')
            .reduceRight((o, k) => o[k] = o[k] || {}, object);
        return object;
    }, {});

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

Answer №2

It appears that this solution should work well for your provided sample data:

const relationships = [
   {id: 'c=de',          parent: null,            child: 'o=group1'},
   {id: 'o=group1',      parent: 'c=de',          child: 'ou=unit1'},
   {id: 'ou=unit1',      parent: 'o=group1',      child: 'ou=smallUnit1'},
   {id: 'ou=smallUnit1', parent: 'ou=unit1',      child: 'cn=devops'},
   {id: 'cn=devops',     parent: 'ou=smallUnit1', child: null}
];

let updatedData = {};
let currentElement = updatedData;

relationships.forEach(relation => {
  currentElement[relation.id] = {};
  currentElement = currentElement[relation.id];
});

console.log(updatedData);

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

Interference in the output of .innerHTML leads to disruption

I have been working on a feature to display a calculated price based on the selected quantity for each individual product. I attempted to duplicate the code and modify variable names, but encountered issues with the increase/decrease buttons triggering mul ...

Using Vue Router's `push()` method within an asynchronous function will solely modify the URL address

I created a custom loading component that displays while the route is being changed. To ensure the loading component properly waits for a second, the method needs to be asynchronous. However, since implementing this feature, I noticed that the router.push ...

Monitoring changes in an array of objects using AngularJS's $watch function

Exploring the world of AngularJS, I'm on a quest to solve a challenging issue efficiently. Imagine having an array of objects like this: var list = [ {listprice: 100, salesprice:100, discount:0}, {listprice: 200, salesprice:200, discount:0}, {listpr ...

The error "JSON is not defined" occurs in Internet Explorer, but not in Chrome

I encountered an issue with my jQuery ajax call in IE9, specifically when utilizing Json.stringify(). An error message appeared: 'Microsoft JScript runtime error: 'JSON' is undefined' Oddly enough, this function was functioning proper ...

What is the best way to retrieve the outcome from the ngbModal component?

I'm seeking assistance with retrieving results from the ngbModal component. I trigger the modal with a link. <a class="order-collection-options-link" (click)="openTimePicker()">{{'ORDER_COLLECTION_OPTIONS_LABEL' | dict}}</a> ...

how can I update a class of an element when the input box is disabled in angular?

Is there a way in Angular to change the class of a separate element (calendar icon button) when it detects that an input textbox is disabled? I have a disabled input type textbox and I want the class of the calendar icon button to be changed based on its d ...

Troubleshooting a Pulumi script in Azure using Typescript and encountering difficulties with function writing

My background is in using terraform, but now I am trying out Pulumi/typescript for the first time. In my codebase, I have two files - index.ts and blob.ts. The create function in blob.ts is responsible for creating a storage account, resource group, blob ...

How to ensure jQuery runs only once, even when the back button is pressed in the

How can I ensure that jQuery only executes once, even when navigating back to the page using the browser's back button? When my page initially loads, the jQuery runs fine. However, if I navigate away from the page and then return using the back button ...

What causes a JSON error upon deleting a list in Replit?

Need assistance with deleting a specific index from a list stored in a json file The json file structure { "0": [ "0", "1", "2", "3" ] } The Python program import json with o ...

Is there a way to transform the XML output from Roku TV's API into JSON format?

I've been working on developing an application that interacts with the Roku TV ECP API commands. One specific call I'm attempting to make retrieves a list of all installed channels and returns it in XML format. However, every time I make this API ...

I am trying to add JSON data to a file, but the output is not in a valid JSON format

I've been tasked with working on a file that prints out messages encoded in JSON format. { "Status": "Non_Malicious", "alert_level": "Low", "alert_count": 1, "alert": "", "hosts_alert": "" } Please note: e ...

Vue.js - Difficulty displaying fetched data from API using v-for

My attempt to render a list of data seems to be hitting a roadblock - the data doesn't display when the page loads. The API call works perfectly, fetching all the necessary data and setting it to my data object. Here's the code snippet: once &apo ...

To enhance user experience, it is recommended to reload the page once

Hello, I'm looking for a way to automatically refresh the page after submitting an AJAX form. Currently, I have an onClick function that seems to refresh the page, but I still need to press F5 to see the changes I've made. Here's the JavaSc ...

Setting values to an array based on the index of a specific name in JavaScript - a guide

How can I set values to an array if it has an index in the name field? Here is the sample data: [ { "column": "created_at[0]", "name": "created_at[0]", "type": "range", ...

What is the best way to retrieve the index and length of an inserted or deleted string within a text area using JavaScript or jQuery?

Is there a way to determine the start and end of a change if a string is inserted or deleted from a textarea (Event)? I am aware of one solution. Save the current string Add an event listener ('change', dosomething); Compare the strings from s ...

Testing the receiveMessage function in SQS using Jest unit tests

Struggling to find the right approach for unit testing this function. I almost have it, but can't quite nail it down. Take a look at the function below: receiveMessage(callback: Function): any { this.sqs.receiveMessage( this.params, ...

The Price Filtering feature in the MERN Stack for Products is currently experiencing technical difficulties

Hey there! I am currently working on developing an Ecommerce Application using the MERN Stack with redux. I've encountered a problem while trying to send a price array argument in my fetching function. The error message states: XHR GET http://localhos ...

How can a key press be simulated without specifically targeting an element?

Is it possible to simulate a key press without targeting any specific element? I found this code snippet: var press = jQuery.Event("keypress"); press.ctrlKey = false; press.which = 75; $("whatever").trigger(press); The above code is used to simulate pres ...

Comma styling in JavaScript

What is the reasoning behind developers choosing to format commas in code this particular way? var npm = module.exports = new EventEmitter , config = require("./lib/config") , set = require("./lib/utils/set"); As opposed to this formatting style? va ...

The retrieval of data from AWS Dynamodb in Node.js is not done synchronously

I recently started working with Node.js and DynamoDB. I created a Node.js SDK to retrieve a single row from a DynamoDB table. The data is being fetched correctly, but there is a delay which is causing an error. Below is a snippet of my code: var AWS = re ...