0

Here we have two main properties, "ID" and "FatherOrganizationID". We need to make a tree where if fatherOranizationId === null -> must be at the top, and if the fatherOrganizationId !== null, it must be in subOrganizations array of items that have ID === FatherOrganizationID. Can someone help with it? Must work in any depth. I know that it is able with recursion but have no mind how to realize it

START DATA:

{
  "id": 1000,
  "organizationName": "testOrg1",
  "fatherOrganizationId": null,
  "subOrganizations": [],
  "isActive": false,
},
{
  "id": 1001,
  "organizationName": "testOrg2",
  "fatherOrganizationId": 1000,
  "subOrganizations": [],
  "isActive": false,
},
{
  "id": 1002,
  "organizationName": "testOrg3",
  "fatherOrganizationId": 1001,
  "subOrganizations": [],
  "isActive": false,
},
{
  "id": 1003,
  "organizationName": "testOrg4",
  "fatherOrganizationId": 1001,
  "subOrganizations": [],
  "isActive": false,
},
{
  "id": 1004,
  "organizationName": "testOrg7",
  "fatherOrganizationId": 1001,
  "subOrganizations": [],
  "isActive": false,
},
{
  "id": 1005,
  "organizationName": "testOrg7",
  "fatherOrganizationId": 1002,
  "subOrganizations": [],
  "isActive": false,
},
{
  "id": 1006,
  "organizationName": "testOrg8",
  "fatherOrganizationId": null,
  "subOrganizations": [],
  "isActive": false,
}

EXPECTED RESULT:

[
{
  "id": 1000,
  "organizationName": "testOrg1",
  "fatherOrganizationId": null,
  "subOrganizations": [
    {
      "id": 1001,
      "organizationName": "testOrg2",
      "fatherOrganizationId": 1000,
      "subOrganizations": [
        {
          "id": 1002,
          "organizationName": "testOrg3",
          "fatherOrganizationId": 1001,
          "subOrganizations": [
            {
              "id": 1005,
              "organizationName": "testOrg7",
              "fatherOrganizationId": 1002,
              "subOrganizations": [],
              "isActive": false,
            }
          ],
          "isActive": false,
        },
        {
          "id": 1003,
          "organizationName": "testOrg4",
          "fatherOrganizationId": 1001,
          "subOrganizations": [],
          "isActive": false,
        },
        {
          "id": 1004,
          "organizationName": "testOrg7",
          "fatherOrganizationId": 1001,
          "subOrganizations": [],
          "isActive": false,
        },
      ],
      "isActive": false,
    },
  ],
  "isActive": false,
},
{
  "id": 1006,
  "organizationName": "testOrg8",
  "fatherOrganizationId": null,
  "subOrganizations": [],
  "isActive": false,
}     
]

1 Answer 1

1

I wrote this code snippet in Typescript, but the concept is the same in C#. It's by no means the fastest algorithm to do this, but it's simple and readable:

type OrgType = {
    id: number;
    organizationName: string;
    fatherOrganizationId: number;
    subOrganizations: OrgType[];
    isActive: boolean;
}

const orgListFromData = JSON.parse(readFileSync("./data.json", 'utf-8')).list as OrgType[];

/**
 * populate organization object 
 * with child organizations 
 */
const populateOrgWithChildren = (organizationsList: OrgType[], organization: OrgType): OrgType => {

    /**
     * get sub organizations, with their subOrganizations already populated,
     * - gets recursive here -
     */
    const subOrganizations = organizationsList
        .filter(org => org.fatherOrganizationId === organization.id)
        .map(org => populateOrgWithChildren(organizationsList, org));

    /**
     * create a new object and spread properties from original, 
     * to avoid mutating original object trough this mem referenence 
     */
    return {
        ...organization,
        subOrganizations
    }
}

/**
 * populate a list of organizations with
 * their child organizations 
 */
const populateOrgs = (organizationsList: OrgType[]) => {

    const rootOrgs = organizationsList
        .filter(x => x.fatherOrganizationId === null);


    const populatedRootOrgs = rootOrgs
        .map(rootOrg => populateOrgWithChildren(organizationsList, rootOrg));

    return populatedRootOrgs;
}

/**
 * Results
 */
const populated = populateOrgs(orgListFromData);

Hope it helps. Tested it myself, works fine. Something that you might want to pay attention to, is that this task is split in 2 parts: you want to find the "root" organizations, and you want to create a hierarchical structure of the rest of the organizations. This is why I split the code into 2 funcitons, populateOrgWithChildren and populateOrgs. The first being the recursive function that can organize the organizations into a tree under a root organization. The second being the function that finds all the root organizations.

Another solution might be to preprocess your data, and assign every organization with null parent id a parent id of let's say -1, and add a new node called "root" with the id -1. (- to denote that it's not a real id from the DB). After this, you can run only the populateOrgWithChildren on the node that has -1 as it's id, since the whole tree will be of the same structure, there's not going to be null id's anywhere. The resut would be a tree that starts with a single root node, which has a made up id, and all the other organizations would rest under that node.

A little help: TS's .filter() equals to C# (LINQ's) .Where().

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.