Repetitive cycling through an array

My array consists of classes:

const transferClasses = [
  {
    id: "c5d91430-aaab-ed11-8daf-85953743f5cc",
    name: "Class1",
    isTransfer: false,
    children: [],
  },
  {
    id: "775cb75d-aaab-ed11-8daf-85953743f5cc",
    name: "Class2",
    isTransfer: false,
    children: [
      {
        id: "89134f56-3ef6-ed11-8daf-85953743f5cc",
        name: "Class2-1",
        isTransfer: false,
        children: [],
      },
      {
        id: "89134f56-3ef6-ed11-8daf-85953743f4cc",
        name: "Class2-2",
        isTransfer: false,
        children: [
          {
            id: "89134f56-3ef6-ed11-8daf-85953743f4de",
            name: "Class2-2-1",
            isTransfer: false,
            children: [],
          },
          {
            id: "89134f56-3ef6-ed11-8daf-85953743f1ce",
            name: "Class2-2-2",
            isTransfer: false,
            children: [],
          },
        ],
      },
    ],
  },
];

I am looking to convert this nested array into a flat list. For example:

const flatList = [
  {
    id: "c5d91430-aaab-ed11-8daf-85953743f5cc",
    name: "Class1",
    isTransfer: false,
    childrenId: null,
    parentId: null,
  },
  {
    id: "775cb75d-aaab-ed11-8daf-85953743f5cc",
    name: "Class2",
    isTransfer: false,
    childrenId: [
      "89134f56-3ef6-ed11-8daf-85953743f5cc",
      "89134f56-3ef6-ed11-8daf-85953743f4cc",
    ],
    parentId: null,
  },
  {
    id: "89134f56-3ef6-ed11-8daf-85953743f5cc",
    name: "Class2-1",
    isTransfer: false,
    childrenId: [],
    parentId: ["775cb75d-aaab-ed11-8daf-85953743f5cc"],
  },
  {
    id: "89134f56-3ef6-ed11-8daf-85953743f5cc",
    name: "Class2-2",
    isTransfer: false,
    childrenId: [
      "89134f56-3ef6-ed11-8daf-85953743f4de",
      "89134f56-3ef6-ed11-8daf-85953743f1ce",
    ],
    parentId: ["775cb75d-aaab-ed11-8daf-85953743f5cc"],
  },
  {
    id: "89134f56-3ef6-ed11-8daf-85953743f4de",
    name: "Class2-2-1",
    isTransfer: false,
    childrenId: [],
    parentId: ["89134f56-3ef6-ed11-8daf-85953743f5cc"],
  },
  {
    id: "89134f56-3ef6-ed11-8daf-85953743f1ce",
    name: "Class2-2-2",
    isTransfer: false,
    childrenId: [],
    parentId: ["89134f56-3ef6-ed11-8daf-85953743f5cc"],
  },
];

Each element should have the ids of its parents and children listed.

Below is my function code. While I've handled the children, I'm stuck on how to include the parents.

export const getFlatList = (classes) => {
  return classes.map((cl) => {
    
    const getChildIds = (classes) => {
      return classes.map((cl) => {
        if (cl.children.length > 0) {
          getChildIds(cl.children);
        } else {
          return cl.id;
        }
        return cl.id;
      });
    };

    return {
      id: cl.id,
      name: cl.name,
      isTransfer: cl.isTransfer,
      children: getChildIds(cl.children),
      parentId: ?? // :(
    };
  });
};

Answer №1

I devised a method similar to this. We begin our search from the top and then proceed to explore any children nodes. If there are children present, we delve one level deeper until we reach the end of the children array.

const flattenNestedArray = (nestedArray) => {
    let flatArray = [];

    const traverseNodes = (node, parentNodeId = null) => {
        const { children, ...otherProperties } = node;

        flatArray.push({
            ...otherProperties,
            childrenIds: children ? children.map(child => child.id) : [],
            parentIds: [parentNodeId],
        });

        if (node.children.length) {
            node.children.forEach((childNode) => traverseNodes(childNode, node.id));
        }
    }

    nestedArray.forEach((arrayItem) => traverseNodes(arrayItem));

    return flatArray;
}

jsfdl: https://jsfiddle.net/wlecki/34cL8jh1/

Answer №2

One way to streamline the process is by implementing a function called getFlatList(). This function can be designed to flatten the input data using a recursive strategy, where it iterates through each element in the input and adds it to an array as a result.

It's essential to include both the parentId and childrenId for every new object that is created in the output

function getFlatList ( input, parentId = null) {
    let result = [];
    for(let key in input) {
        if (input[key] && typeof(input[key]) === 'object') {
          if (input[key].name) {
              const { children, ...object } = input[key]
              result.push({
                  ...object,
                  childrenId: children.map(child => child.id),
                  parentId
              })
          }
          result.push(...getFlatList(input[key], input.id))
        }
    }
    return result;
}

const transferClasses = [ { id: "c5d91430-aaab-ed11-8daf-85953743f5cc", name: "Class1", isTransfer: false, children: [], }, { id: "775cb75d-aaab-ed11-8daf-85953743f5cc", name: "Class2", isTransfer: false, children: [ { id: "89134f56-3ef6-ed11-8daf-85953743f5cc", name: "Class2-1", isTransfer: false, children: [], }, { id: "89134f56-3ef6-ed11-8daf-85953743f4cc", name: "Class2-2", isTransfer: false, children: [ { id: "89134f56-3ef6-ed11-8daf-85953743f4de", name: "Class2-2-1", isTransfer: false, children: [], }, { id: "89134f56-3ef6-ed11-8daf-85953743f1ce", name: "Class2-2-2", isTransfer: false, children: [], }, ], }, ], }, ];

console.log('Flattened: ');
console.log(getFlatList (transferClasses))
.as-console-wrapper { max-height: 100% !important; }

Answer №3

My approach to this would be as follows:

const group = (items, parentID = null) => 
  items.flatMap(({children = [], id, ...rest}) => [
    {id, ...rest, parentID, childrenIDs: children.map(({id}) => id)}, 
    ...group(children, id)
  ])

const classes = [{id: "c5d91430-aaab-ed11-8daf-85953743f5cc", name: "Class1", isTransfer: false, children: []}, {id: "775cb75d-aaab-ed11-8daf-85953743f5cc", name: "Class2", isTransfer: false, children: [{id: "89134f56-3ef6-ed11-8daf-85953743f5cc", name: "Class2-1", isTransfer: false, children: []}, {id: "89134f56-3ef6-ed11-8daf-85953743f4cc", name: "Class2-2", isTransfer: false, children: [{id: "89134f56-3ef6-ed11-8daf-85953743f4de", name: "Class2-2-1", isTransfer: false, children: []}, {id: "89134f56-3ef6-ed11-8daf-85953743f1ce", name: "Class2-...
console.log(group(classes))
.as-console-wrapper {max-height: 100% !important; top: 0}

We use flatMap to flatten the list, at each step returning an array with the current item (excluding its children property), and then recursively processing the list of children. The parentID value is passed through the recursion, defaulting to null if not provided, and we extract childrenIDs by selecting the id values from the children objects. Recursion elegantly takes care of everything else for us.

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

JavaScript - changing object into a string (not functioning properly)

Looking to convert a JavaScript object into a string? Here's an example: var obj = {"name": "XXX", "age": "27"}; After doing some research, I found out about JSON.stringify(obj); JSON.stringify(obj); works perfectly when the IE8 modes are set as fo ...

Utilizing namespacing in a JavaScript library can enhance organization and flexibility, providing

Creating a JavaScript library with multiple modules is my next project. Imagine the library is named Library, with modules One and Two. My goal is to allow end users to call the library in two ways: Library.One.somefunction(params) or somefunction(param ...

Loading files using $scriptjs or any other asynchronous loader allows for seamless integration of external resources

Imagine I have developed an AngularJS application that lazy loads controller files (using $scriptjs) and all dependencies when the user navigates to a specific route. This application consists of 3 routes: A, B, and C. My question is: if the user navigate ...

Describing a property of an interface as the determined form of a conditional type that is generic

I am currently working on defining an interface that includes a method with a conditional function definition. For example: interface Example<T> { func: T extends string ? () => string : () => number; } class ExampleClass<T extends str ...

Using a URL in an AJAX request

Before redirecting to another page, I am storing data from a textbox. When the user clicks the back button on the page load function in JavaScript, I retrieve the data from the textbox using: var pageval = $('#grid') .load('/Dealer/AllClai ...

Is it possible to transform a webpack configuration into a Next.js configuration?

i have come across a webpack configuration setup from https://github.com/shellscape/webpack-plugin-serve/blob/master/recipes/watch-static-content.md: const sane = require('sane'); const { WebpackPluginServe: Serve } = require('webpack-plugin ...

How to Nest Interfaces in TypeScript

I'm just starting to learn about Angular and I am having trouble getting the interface class to work properly. export interface Header { parentTitles: string; childHeaders: ChildHeader[]; titleIcon: string; url: string; } export interf ...

Guide on integrating google play services into a nativescript plugin seed?

I am developing a plugin for NativeScript using the recommended nativescript-plugin-seed available at this link. In my plugin, I require access to the Google Location service, but I am facing issues with accessing it. In order to implement the required de ...

``To increase a value within an array object in MongoDB with the use of nodejs, what steps should be

Within my node.js application, I have a MongoDB post model that includes an array of comments. Each comment has a "likes" field representing the number of likes it has received. I want to increment this value for each comment individually. How can I achiev ...

Sending Node.js FileStream Image to HTML5 FileReader API

Is there a way to utilize Node FileSystem for opening a file and then having it read by the FileReader API? const myFile = "C:\\Users\\Me\\Image.png"; fs.readFile(myFile, (error, data) => { const blob = new B ...

Using React - What is the best way to invoke a function from within a different function?

Imagine this scenario: class Navigation extends React.Component { primaryFun() { console.log('funn') } secondaryFun() { this.primaryFun(); } } I assumed that calling primaryFun within secondaryFun would work as expected, but instead I rec ...

Webpack encounters an error while attempting to load Bootstrap v4.0.0-beta

I've encountered an issue with my webpack configuration and Bootstrap v4.0.0-alpha.6 that was working fine until I attempted to switch to v4 beta. Unfortunately, I can't seem to get it working properly now :( Here is a snippet of my config: w ...

How can we store image file paths in MongoDB?

I'm currently working on developing a REST API using nodeJS, express, mongoose, and mongodb. I have successfully implemented file uploads with multer and saved the files to a folder. Now, I need to save the path of the uploaded file to a mongodb docum ...

Pattern matching for validating multiple email addresses

I need assistance with validating multiple email inputs using regex in Angular. I am looking to enforce a specific format for the emails, such as: Examples: *****@zigurat.com *****@test.com *****@partlastic.com The ***** can be any characters, but the ...

Receive live feedback from shell_exec command as it runs

I have been working on a PHP-scripted web page that takes the filename of a previously uploaded JFFS2 image on the server. The goal is to flash a partition with this image and display the results. Previously, I had used the following code: $tmp = shell_ex ...

Creating a "Container" component in Vue.js step by step

As a newcomer to Vue, I am facing a challenge in implementing a wrapper component similar to React's 'Wrapper' component. Specifically, I want to create a reusable datagrid component using a 3rd-party some-table component and a pagination co ...

Identification of input change on any input or select field within the current modal using JavaScript

My modal contains approximately 20 input and select fields that need to be filled out by the user. I want to implement a JavaScript function to quickly check if each field is empty when the user navigates away or makes changes. However, I don't want t ...

Three.js fails to load due to Require.js issue

Having encountered a JavaScript error in browser (on the last line mentioned above) with generated code from TypeScript: define(["require", "exports", "three", "jquery", "./test"], function (require, exports, THREE, jQuery, Test) { var Main = (function () ...

React is unable to access and retrieve data from a web API

Currently, I have a controller set up in web-api for my project. I am using React v18.2.0 and NextJS v13.3.0 to work with this setup: public List<ReturnDat> Get() { List<ReturnDat> lst = new List<ReturnDat>(); lst.Add(new ReturnD ...

What is the process of declaring a react-icons icon in TypeScript?

Having a dilemma with declaring the icon in my array that contains name and icon. export const SidebarMenuList: SidebarMenu[] = [ { name: "Discover", icon: <AiOutlineHome />, id: SidebarCategory.Discover, }, ] The SidebarMe ...