Generating a flat array structure in Javascript using data from various nested levels

I need help creating a stacked bar chart similar to the one shown in this example: http://jsfiddle.net/fct1p8j8/4/

While the hard-coded data works perfectly fine, I'm struggling to extract and format the data from my database structure.

My data is organized as follows:

[
  {
    "invDept": "Due Diligence",
    "programs": {
      "data": [
        {
          "program": "Brand Risk Management",
          "total": "1847"
        },
        {
          "program": "Due Diligence",
          "total": "2718"
        },
        {
          "program": "SAR",
          "total": "17858"
        }
      ]
    }
  },
  {
    "invDept": "Sanctions",
    "programs": {
      "data": [
        {
          "program": "Brand Risk Management",
          "total": "500"
        },
        {
          "program": "Due Diligence",
          "total": "2100"
        },
        {
          "program": "SAR",
          "total": "16593"
        }
      ]
    }
  }
]

The x-axis values will be based on the invDepartment, while the series data needs to be formatted correctly for the chart.

I am attempting to organize the data into an array format where each program's value corresponds to both the Due Diligence and Sanctions departments.

Currently, I have started by initializing a loop to create the necessary structure:

// Obtain department values for X Axis

$.each(data.data, function (key, value) {

    d = value;

    xAxis.push(value.invDept);

    // Create array if it does not exist
    if (typeof res[d.invDept] == "undefined" || !(res[d.invDept] instanceof Array)) {
        res[d.invDept] = [];
    }

});

At this point, I have:

res['Due Diligence'] = []

However, I am unsure of how to proceed further in structuring the loops to extract this data effectively.

The desired output should resemble:

series: [{
    name: 'Brand Risk Management',
    data: [1847, 500]
}, {
    name: 'Due Diligence',
    data: [2718, 2100]
}, {
    name: 'SAR',
    data: [17858, 16593]
}]

Answer №1

Utilize the power of Array.concat(), Array.map() functions, along with the spread syntax to condense the data into a unified array.

Next, apply the reduce method on the array to create a Map that combines objects sharing the same key for the desired output. Once completed, revert the Map back to an array using Map.values() paired with the spread syntax.

const data = [{"invDept":"Due Diligence","programs":{"data":[{"program":"Brand Risk Management","total":"1847"},{"program":"Due Diligence","total":"2718"},{"program":"SAR","total":"17858"},{"program":"Sanctions - WLM","total":"885"}]}},{"invDept":"Sanctions","programs":{"data":[{"program":"Brand Risk Management","total":"500"},{"program":"Due Diligence","total":"2100"},{"program":"SAR","total":"16593"},{"program":"Sanctions - WLM","total":"443"}]}}]

const result = [... // spread the iterator to a new array
  // flatten the array
  [].concat(...data.map(({ programs }) => programs.data))
  // reduce the data into a map
  .reduce((r, { program: name, total }) => {
      // if key doesn't exist create the object
      r.has(name) || r.set(name, { name, data: [] }) 
      // get the object, and add the total to the data array
      r.get(name).data.push(total) 

      return r;
    }, new Map())
  .values()] // get the Map's values iterator
  
console.log(result)

Answer №2

To simplify this process, you can utilize the built-in function reduce.

var data = [  {    "category": "Category A",    "items": {      "data": [        {          "item": "Item X",          "quantity": "100"        },        {          "item": "Item Y",          "quantity": "200"        },        {          "item": "Item Z",          "quantity": "500"        }      ]    }  },  {    "category": "Category B",    "items": {      "data": [        {          "item": "Item X",          "quantity": "50"        },        {          "item": "Item Y",          "quantity": "150"        },        {          "item": "Item Z",          "quantity": "300"        }      ]    }  }],
    summary = { inventory: Object.values(data.reduce((acc, curr) => {
      curr.items.data.forEach((item) => 
        (acc[item.item] || (acc[item.item] = {data: [], name: item.item})).data.push(item.quantity));
      return acc;
}, {}))};

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

Answer №3

To efficiently process your array and store values in an object accumulator, utilize array#reduce. Utilize programs and data with array#forEach to fill the object accumulator. Finally, retrieve all values using Object.values()

var data = [ { "invDept": "Due Diligence", "programs": { "data": [ { "program": "Brand Risk Management", "total": "1847" }, { "program": "Due Diligence", "total": "2718" }, { "program": "SAR", "total": "17858" }, { "program": "Sanctions - WLM", "total": "885" }] } }, { "invDept": "Sanctions", "programs": { "data": [ { "program": "Brand Risk Management", "total": "500" }, { "program": "Due Diligence", "total": "2100" }, { "program": "SAR", "total": "16593" }, { "program": "Sanctions - WLM", "total": "443" }] } } ],
    result = Object.values(data.reduce((r,o) => {
      o.programs.data.forEach(({program, total}) => {
        r[program] = r[program] || {name: program, data: []};
        r[program].data.push(total);
      });
      return r;
    },{})),
    output = {series: result};
console.log(output);
.as-console-wrapper{ max-height: 100% !important; top: 0;}

Answer №4

To organize the programs, you can utilize the reduce method and create a new object to store each program as its key in an array. If you do not want duplicates, you can replace the array object with a set object and switch out push for add

let myPrograms = data.reduce((accumulator, item) => {
item && item.programs && item.programs.data && accumulateData(item.programs.data);

function accumulateData(program_data) {
  for (let item of program_data) {
    accumulator[item.program] ||
      (accumulator[item.program] = [item.total],
        accumulator[item.program].push(item.total));
  }
}
return accumulator;
}, {});

You can access the array of data within myPrograms like so:

myPrograms["program name"];

let data = [{
    "invDept": "Due Diligence",
    "programs": {
      "data": [{
          "program": "Brand Risk Management",
          "total": "1847"
        },
        {
          "program": "Due Diligence",
          "total": "2718"
        },
        {
          "program": "SAR",
          "total": "17858"
        },
        {
          "program": "Sanctions - WLM",
          "total": "885"
        }
      ]
    }
  },
  {
    "invDept": "Sanctions",
    "programs": {
      "data": [{
          "program": "Brand Risk Management",
          "total": "500"
        },
        {
          "program": "Due Diligence",
          "total": "2100"
        },
        {
          "program": "SAR",
          "total": "16593"
        },
        {
          "program": "Sanctions - WLM",
          "total": "443"
        }
      ]
    }
  }
];

let myPrograms = data.reduce((accumulator, item) => {
  item&&item.programs&&item.programs.data&& 
  accumulateData(item.programs.data);

  function accumulateData(program_data) {
    for (let item of program_data) {
      accumulator[item.program] || (accumulator[item.program] = [item.total], accumulator[item.program].push(item.total));
    }
  } 
  return accumulator;
}, {});

console.log(myPrograms);
console.log(myPrograms["Brand Risk Management"]);

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

Client-Specific User Portal

Looking for some support on the back end of things. We are in the process of creating a portal where users will be directed to their specific landing pages upon logging in, providing access to files they have signed up for. Our team is exploring the use ...

Having trouble with string matching in JavaScript?

My attempts to verify my Ajax response with a string have consistently resulted in a fail case being printed. Below is the section of code relating to my ajax request: var username = document.getElementById("name").value; var password = document.getEle ...

Function parameter accepting an anonymous value object

While working with prisma nexus and examining the prismaObjectType, I came across something unusual. A simple example of this is as follows: In a basic function, demo(p), the parameter p should be an object. function demo(p) { console.log(p); con ...

``A fire tag is assigned depending on the existence of a div element

I have a task I need to complete on Wordpress blog pages, however there is no specific identifier in the URL. Instead, there are differences in content that can be used. Is there a method to trigger a tag (or event) based on the presence of a particular ...

Challenge encountered in handling AJAX response data for presentation

Currently, I am immersed in a project and decided to implement AJAX for smoother form submissions. My initial attempt was trying to display text from a .txt file below the "submit" button, but unfortunately, that approach didn't yield the desired resu ...

Determine whether an element has the capability to hold text content

Is there a surefire and reliable method to determine if an HTML element is capable of holding text, using only pure JavaScript or jQuery? For example, <br>, <hr>, or <tr> cannot contain text nodes, whereas <div>, <td>, or < ...

Implement an event listener in a PHP server-side file to capture the onClick event with the

I am completely new to working with Ajax. In my application, I am using ajax along with a server-side php page named Req.php to retrieve records from a database, generate a table based on those fetched records, and then display it. Now, I am looking to inc ...

Steps for storing a JSON string containing several objects into a JavaScript variable

I'm working with a JSON that contains multiple objects, and it's possible for this JSON string to have more data/objects than just three. My goal is to create an array of objects regardless of how much information is included. [ {"endDate":"2017 ...

Using Vue.js to invoke an external JavaScript function for search functionality

In my vue.js application, I have a list of users with backend pagination. Now I want to implement a search functionality. I attempted to call the method like this: watch: { search: function() { Crud.methods.getItems(); } }, Howe ...

Learn the process of using Angular Js to compare checkbox values with stored comma-separated values in a database

When displaying amenity checkbox options using ng-repeat of a JSON array and saving them into the database as comma-separated IDs like "1,3,7" within a single string, the challenge arises when needing to edit the amenities. This is due to retrieving the ex ...

The React implementation of an OpenLayers map is not responsive on mobile devices

I recently set up an OpenLayers map in a React project and it's working smoothly on desktop browsers. The map is interactive, allowing users to drag, zoom in/out, and display markers as expected. However, I'm facing an issue with touch events on ...

The recall function in Jquery (within an updatepanel) does not exhibit seamless performance

There is a jQuery function that toggles the visibility of the "ReplyComment" div. function toggleReplyDiv() { $('.in').click(function () { var $this = $(this), $reply = $this.next('.ReplyComment'); var d ...

Create HTML div elements dynamically with JavaScript based on database information

Can javascript be used to create divs from database information? ...

using javascript to get array element when hovering

I am currently exploring ways to retrieve and display the value of a div tag created with a 2D array using JavaScript. I have considered using onclick or onmouseover, but so far, neither approach has worked as expected. I am looking for a solution that avo ...

What sets apart $.replaceWith() from the combination of $.remove and $.appendTo()?

I have noticed that when using these two pieces of code, I get different outcomes. In theory, they should yield the same result. What exactly sets them apart? var mapString = '<map id="map"><area shape="poly" coords="52,21,92,21,92,196,52,19 ...

What is the step-by-step process to upload a file along with JSON data using fetch and multer

My task involves uploading a file along with some metadata on a JSON object using the "fetch" JavaScript native function on the client side and Express with the multer middleware on the server side. Client Side: const formData = new FormData() formData.a ...

Having trouble initiating NPM in a terminal

I keep encountering an issue whenever I try to start NPM using a command in the terminal. Here is the error message that appears: npm ERR! npm ERR! Did you mean one of these? npm ERR! npm star # Mark your favorite packages npm ERR! npm stars # Vi ...

Guide to assigning positions in an array of a particular component with its selector utilizing Angular:

I am a beginner when it comes to Angular and I have a question regarding setting positions of an array that is initially declared as empty in one component, using its selector in another component. Let's take for example a component named "array" whe ...

Include a new row in the form that contains textareas using PHP

I'm trying to add a new row to my form, but I'm facing challenges. When I click the add button, nothing happens. If I change the tag to , then I am able to add a row, but it looks messy and doesn't seem correct to me. Here is my JavaScript ...

Getting the total number of child elements in a web page using Selenium web-driver with Node.js

I've been looking everywhere, but I can't seem to find the answer Here's my HTML code: <form id="search_form_homepage" > ... <div class="search__autocomplete" style="display: block;"> &l ...