Looping through an array within an object and dynamically adding properties

Having an issue with recursion regarding the following data:

let data = {
    label: "Root",
    datasets: [
        {
            label: "Parent 1"
            datasets: [
                {
                    label: "Child 1",
                    dataMax: 100,
                    datasets: 30
                },
                {
                    label: "Child 2",
                    dataMax: 30,
                    datasets: 30
                }
            ]
        },
        {
            label: "Parent 2",
            dataMax: 50,
            datasets: 30
        }
    ]
};

The goal is to add a dataMax property and values in every parent that does not have one, and for parents with multiple children, the dataMax should contain the total of its children's values.

Note that the depth and length of data are variable.

Here is what has been attempted so far:

let data = {
          label: "Root",
          datasets: [
              {
                  label: "Parent 1",
                  datasets: [
                      {
                          label: "Child 1",
                          dataMax: 100,
                          datasets: 30
                      },
                      {
                          label: "Child 2",
                          dataMax: 30,
                          datasets: 30
                      }
                  ]
              },
              {
                  label: "Parent 2",
                  dataMax: 50,
                  datasets: 30
              }
          ]
      };

      let setDatas = function(x, i, p){
          if (x == undefined) {
              console.log("--- This is x==undefined ---");
              return 1;
          } else if (Array.isArray(x.datasets)) {
              console.log("-------------- " + x.label + ", datasets[" + [i] + "]:");
              console.log(x.datasets[i]);
              return setDatas(x.datasets[i], i, x);
          } else {
              console.log("It's not an Array");
              ++i;
              return setDatas(p, i, p);
          }
      }

      setDatas(data, 0);

Managed to reach the desired depth but struggling to return to the root. It feels like something is missing. What could be wrong?

Expected Output:

let data = {
    label: "Root",
    dataMax: 180, // Total sum from Parent 1 and 2 dataMax values
    datasets: [
        {
            label: "Parent 1",
            dataMax: 130, // Total sum of "Child 1" and "Child 2" dataMax values
            datasets: [
                {
                    label: "Child 1",
                    dataMax: 100,
                    datasets: 30
                },
                {
                    label: "Child 2",
                    dataMax: 30,
                    datasets: 30
                }
            ]
        },
        {
            label: "Parent 2",
            dataMax: 50,
            datasets: 30
        }
    ]
};

Appreciate any assistance or further information required. Thank you.

Answer №1

Ensure to iterate over the nested data.datasets in your function, not just check for the given data.

You can utilize a mix of Array#map() and Array#reduce() methods as shown below:

function calculateMax(data) {
  if (data.datasets && Array.isArray(data.datasets)) {
    data.datasets = data.datasets.map(item => {
      if (!item.dataMax) {
        if (Array.isArray(item.datasets)) {
          // For nested datasets, make recursive call
          calculateMax(item);
        }
      }
      return item;
    });
  }
  if (!data.dataMax)
    data.dataMax = data.datasets.map(item => item.dataMax).reduce((a, b) => (a + b));
}

Example:

let dataSet = {
  label: "Root",
  datasets: [{
      label: "Parent 1",
      datasets: [{
          label: "Child 1",
          dataMax: 100,
          datasets: 30
        },
        {
          label: "Child 2",
          dataMax: 30,
          datasets: 30
        }
      ]
    },
    {
      label: "Parent 2",
      dataMax: 50,
      datasets: 30
    }
  ]
};


function calculateMax(data) {
  if (data.datasets && Array.isArray(data.datasets)) {
    data.datasets = data.datasets.map(item => {
      if (!item.dataMax) {
        if (Array.isArray(item.datasets)) {
          calculateMax(item);
        }
      }
      return item;
    });
  }
  if (!data.dataMax)
    data.dataMax = data.datasets.map(item => item.dataMax).reduce((a, b) => (a + b));
}
calculateMax(dataSet);
console.log(dataSet)

Answer №2

Let's test this out:

information = {
    label: "Main",
    datasets: [{
        label: "First Parent",
        datasets: [{
            label: "First Child",
            dataMax: 100,
            datasets: 30
        }, {
            label: "Second Child",
            dataMax: 30,
            datasets: 30
        }]
    }, {
        label: "Second Parent",
        dataMax: 50,
        datasets: 30
    }]
}

function updateData(information) {
    if (Array.isArray(information.datasets)) {
        let childMaximum = 0;

        for (let i = 0; i < information.datasets.length; i++) {
            childMaximum += updateData(information.datasets[i]);
        }

        if (information.dataMax === undefined) {
            information.dataMax = childMaximum;
        }
    }

    return information.dataMax;
}

updateData(information);

Answer №3

One way to achieve this is by utilizing the .reduce method in JavaScript, which allows you to maintain the original data intact.

const datasets = [
        {
            label: "Parent 1",
            datasets: [
                {
                    label: "Child 1",
                    dataMax: 100,
                    datasets: 30
                },
                {
                    label: "Child 2",
                    dataMax: 30,
                    datasets: 30
                }
            ]
        },
        {
            label: "Parent 2",
            dataMax: 50,
            datasets: 30
        }
    ]; 

const refinedDataset = datasets.reduce((prev, curr) => {
    if (curr.dataMax) { 
        return prev.concat([curr]);
    } else {
        if (curr.datasets.length > 0) {
            const dataMax = curr.datasets.reduce((pds, cds) => pds += cds.dataMax, 0);
            const nds = Object.assign(curr, { dataMax });
            return prev.concat([nds]);
        }
    }
}, []);

console.log(refinedDataset);

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

What is the process for creating JavaScript code to append a div element for each item?

var p=$('.Tex_1st_con_mes p'); while ($(p).outerHeight()>80) { $(p).text(function (index, text) { return text.replace(/\W*\s(\S)*$/, '...'); }); } $(document).on('click','button&a ...

What is causing TypeScript to compile and remove local variables in my Angular base controller?

I am trying to develop a base controller in Typescript/Angular for accessing form data, but I'm encountering an issue where the form member seems to be getting removed during compilation and is not present in the generated JavaScript code. Could you ...

Issue with Vue js counter increment and decrement function not performing as anticipated

Here we have an example of a dummy project: An app with a counter feature that allows for both increment and decrement functions which change two different values ("life" and "count") and also keeps a record of the changes. The "life" value behaves as exp ...

Enhancing HTML through Angular 7 with HTTP responses

Sorry to bother you with this question, but I could really use some help. I'm facing an issue with updating the innerHTML or text of a specific HTML div based on data from an observable. When I try to access the element's content using .innerHTM ...

The argument type 'bool' in EAzureBlobStorageFile is unrecognized, along with the exception '*** -[__NSArrayM objectAtIndexedSubscript:]'

Encountered some issues... An error occurred with an unknown argument '_Bool' in the method -[EAzureBlobStorageFile configure:key:container:token:]. It seems that RCTConvert needs to be extended to support this type. Also, there was an exceptio ...

Tips for extracting values using forEach in JavaScript

I typically utilize array.forEach(element=>console.log(element) to view the contents of an array, but now I am interested in extracting the actual values. Consider the following snippet: array=['1','2','3','4'] ...

Tips for altering an element's style attribute using ERB and JQuery while including a % symbol within the value

I'm attempting to adjust the style="width: 5%" attribute of a span using Jquery and AJAX. This width needs to be specified in percentage as it represents a progress bar. Here is my code snippet from html.erb: <div class="progress success round" ...

Displaying Real-Time Values in ReactJS

Hi there, I am currently using the code below to upload images to Cloudinary: import React, { Component } from 'react'; import './App.css'; import Dropzone from 'react-dropzone'; import axios from 'axios'; const F ...

Nuxt and Webpack error: Failed to parse module - Unexpected character (1:0)

https://i.sstatic.net/ope8z.png I am working on a Vue carousel component and my goal is to dynamically generate a list of .png files from the static folder. I have followed instructions from here and also from here. Below is an excerpt from my component: ...

Using Angular 4 Component to Invoke JavaScript/jQuery Code From an External File

I have written a jQuery code that is executed at ngAfterViewInit(). //myComponent.ts ngAfterViewInit() { $(function () { $('#myElement').click(function (e) { //the code works fine here }); } However, I want t ...

Creating a new application to manage and oversee my mathematics classes

As a mathematician with experience in programming, I run a successful (Math) YouTube channel and offer paid math courses. I am looking to create a web application or customize an existing template that will enable me to manage access to my classes (priva ...

modifying output of data when onchange event is triggered

I am struggling with creating an onchange event for my option box in which the users of a site are listed. I have two input boxes designated for wins and losses, but the output is not changing when I select a user from the list. What could be wrong with my ...

Detect if the user is using Internet Explorer and redirect them to a different

My web application is having trouble rendering in Internet Explorer. In the meantime, I would like to detect if the user is using IE and redirect them to a different page specifically for IE visitors. What is the best way to accomplish this? Should I use ...

Navigating protected routes in a React application

Currently, I am facing an issue with my private routing setup. In my App.js code, I am using the user variable to determine if a user is logged in or not, and restrict access to private routes accordingly. However, there is a delay in fetching user data fr ...

Error: Attempting to use the 'append' method on an object that does not support the FormData interface

$(document).on('submit','#form_pem', function(event){ event.preventDefault(); var kode = $('#kode').val(); var name = $('#name').val; var price = $('#price'). ...

Submit a data array using formData through axios

I am planning to send array data using formData. The backend is set up to accept the data array separated by a dash ; For example, if I were to use Postman and input the form-data like this: id_barang : 122;288;383 (sending 3 values of id with dashes ;) W ...

Encountering an 'error' event during installation of the Meteorite router package with the command 'mrt add router'

Encountering an issue with mrt add router, I am receiving the following exception/error message: events.js:74 throw TypeError('Uncaught, unspecified "error" event.'); ^ TypeError: Uncaught, unspecified "error" event. at ...

What is the best way to implement consts from various files in React JS?

Could you please guide me on how to utilize consts from separate JS files in React? My goal is to calculate the total score of 4 different Quiz scores (Average). Thanks in advance! I attempted to export and import but encountered issues. Here is the cod ...

Transfer the value of a JavaScript variable to paste it into a fresh tab on Google Chrome

I have come across some examples where users can copy HTML text to the clipboard. However, I am working on something more dynamic. Here's what I'm trying to achieve: <button id="" ng-click="outputFolder()">Output Folder</button> $sc ...

What is the process for setting a particular array list to designated data?

How can I retrieve a unique list of affiliation values from the DB column setting_name in the table author_settings, excluding duplicates? Here is the database structure: author_id | setting_name | setting_value 1 affiliation King College ...