Utilizing ES6 array methods to convert multidimensional arrays into chart-ready data

Seeking help with converting an array to a specific data format for chart display.

The chrart.js library requires data in the following format:

dataset = [ { label: 'one', data: []}, 
           {label: 'two', data: []}
        ];

I receive response data in another format, which is in random order and needs to be appropriately changed with the respective labels.

Here is the code and trial I have attempted:

const dataset = [
    {
        detail: {
            team: [
                { name: 'alpha', game: 1 },
                { name: 'beta', game: 1 },
                { name: 'gamma', game: 1 },
                { name: 'delta', game: 1 },
                { name: 'echo', game: 1 }
            ]
        }
    },
    // more data objects here...
];

const teams = dataset.map(ds => ds.detail.team);
let z = teams.map(element => {
    return element.map(e => {
        let p = {};
        let n = e.name;
        let c = e.game;
        p[n] = c;
        return p;
    });
});

console.log('z', z);

let nt = [];

z.reduce((c, n, i, a) => {
    let z1 = n.map(i => {
        console.log(i);
        let entries = Object.entries(i);
        return entries.map(e => {
          return { label: e[0], data: e[1] };
        });
    });
    return z1;
}, [])

Desired output:

[
    {
        label: 'alpha',
        data: [1, 2, 0, 0, 2, 0]
    },
    // more formatted data objects...
]

I am struggling with the array.reduce method to achieve the desired output. Any ES6 solution suggestions would be greatly appreciated.

If you can provide any insights or assistance, it would be highly valued. Thank you!

Answer №1

Let's keep your dataset as is and build up from scratch to achieve the desired output.

First step: de-nest the data:

dataset.map(d => d.detail.team)

Next, consolidate all teams into a single array:

dataset
  .map(object => object.detail.team)
  .reduce((acc, team) => acc.concat(team))

Now that we have a unified list of names and games, let's transform this into a hash:

dataset
  .map(object => object.detail.team)
  .reduce((acc, team) => acc.concat(team))
  .reduce((acc, team) =>{
    acc[team.name] = acc[team.name] || []
    acc[team.name].push(team.game)
    return acc
  }, {})

We now possess a hash mapping names to games. By using Object.entries on this hash, we can obtain label pairs:

Object.entries(
  dataset
    .map(object => object.detail.team)
    .reduce((acc, team) => acc.concat(team))
    .reduce((acc, team) =>{
      acc[team.name] = acc[team.name] || []
      acc[team.name].push(team.game)
      return acc
    }, {})
)

Finally, we can iterate over these pairs to formulate the final object:

Object.entries(
  dataset
    .map(object => object.detail.team)
    .reduce((acc, team) => acc.concat(team), [])
    .reduce((acc, team) =>{
      acc[team.name] = acc[team.name] || []
      acc[team.name].push(team.game)
      return acc
    }, {})
)
  .map(([team, games]) => ({ team, games }))

The challenge lies in consolidating these steps together efficiently.

Surprisingly, most steps can be combined! Simply loop over each object, manually reference the structure, iterate through individual team arrays, and construct our hash.

Object.entries(
  dataset
    .reduce((acc, object) =>{
      object.detail.team.forEach(team =>{
        acc[team.name] = acc[team.name] || []
        acc[team.name].push(team.game)
      })
      return acc
    }, {})
)
  .map(([team, games]) => ({ team, games }))

Additional Details

Introduction to Arrow Functions

In our example, arrow functions were utilized to embrace ES6 standards, fulfilling the request for modern syntax usage. For more insights on arrow functions, refer to the MDN documentation. Essentially, they offer a concise way to define functions:

function test(value){ return console.log(value) }
// equivalent to
let test = value => console.log(value)

function add(a, b){ return a + b)
// equivalent to
let add = (a,b) => a + b

Exploring Array.prototype.forEach()

In our streamlined approach, we leveraged Array.prototype.forEach() to modify the accumulator without explicit returns. Unlike methods designed for returning values, forEach excels at facilitating side effects quickly, perfect for our scenario where tweaking the accumulator shape is paramount.

Diving Into Destructuring Arrays

Introducing destructuring - a handy feature allowing retrieval of values from predictable object or array structures. For a comprehensive overview, visit the MDN guide. Here's a snippet showcasing its power:

var a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20

[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]

({ a, b } = { a: 10, b: 20 });
console.log(a); // 10
console.log(b); // 20

Answer №2

To achieve the desired output, one can utilize the Array.reduce() method to create a map and then use that map accordingly.

const dataset = [{detail:{team:[{name:'alpha',game:1},{name:'beta',game:1},{name:'gamma',game:1},{name:'delta',game:1},{name:'echo',game:1}]}},{detail:{team:[{name:'alpha',game:2},{name:'beta',game:2},{name:'echo',game:2},{name:'gamma',game:2},{name:'delta',game:2}]}},{detail:{team:[{name:'echo',game:1},{name:'delta',game:0},{name:'beta',game:0},{name:'gamma',game:0},{name:'alpha',game:0}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:0},{name:'beta',game:0},{name:'gamma',game:1},{name:'alpha',game:0}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:0},{name:'alpha',game:2},{name:'gamma',game:3},{name:'beta',game:2}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:1},{name:'beta',game:0},{name:'gamma',game:2},{name:'alpha',game:0}]}}];
var map = dataset.reduce((a,curr)=>{
    curr.detail.team.forEach((e)=> (a[e.name]= (a[e.name] || [])).push(e.game));
    return a;
}, {});
var result =[];

Object.keys(map).forEach((key)=>{
  result.push({
    "label" : key,
    "data" : map[key]
  });
});

console.log(result);

Answer №3

One approach is to utilize the reduce method to transform an array into a flat structure, followed by iterating over it to achieve the desired output format.

const dataset = [{detail:{team:[{name:'alpha',game:1},{name:'beta',game:1},{name:'gamma',game:1},{name:'delta',game:1},{name:'echo',game:1}]}},{detail:{team:[{name:'alpha',game:2},{name:'beta',game:2},{name:'echo',game:2},{name:'gamma',game:2},{name:'delta',game:2}]}},{detail:{team:[{name:'echo',game:1},{name:'delta',game:0},{name:'beta',game:0},{name:'gamma',game:0},{name:'alpha',game:0}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:0},{name:'beta',game:0},{name:'gamma',game:1},{name:'alpha',game:0}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:0},{name:'alpha',game:2},{name:'gamma',game:3},{name:'beta',game:2}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:1},{name:'beta',game:0},{name:'gamma',game:2},{name:'alpha',game:0}]}}];
const flat = dataset.reduce( (a,b) => a.concat(b.detail.team), []);
let result = [];

for (let element of flat) {

  let match = null;

  for (let e  of result) {
    if (e.label === element.name) {
      match = e;
    }
  }

  if (match) {
    match.data.push(element.game)
  }
  else {
    result.push({
      label : element.name,
      data  : [element.game]
    });
  }

}

console.log(result);

Answer №4

Try this alternative approach: iterate through the data set as is and save the outcomes in a dictionary-like object called map, while also storing them in the result array to be returned.

const dataset = [{detail:{team:[{name:'alpha',game:1},{name:'beta',game:1},{name:'gamma',game:1},{name:'delta',game:1},{name:'echo',game:1}]}},{detail:{team:[{name:'alpha',game:2},{name:'beta',game:2},{name:'echo',game:2},{name:'gamma',game:2},{name:'delta',game:2}]}},{detail:{team:[{name:'echo',game:1},{name:'delta',game:0},{name:'beta',game:0},{name:'gamma',game:0},{name:'alpha',game:0}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:0},{name:'beta',game:0},{name:'gamma',game:1},{name:'alpha',game:0}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:0},{name:'alpha',game:2},{name:'gamma',game:3},{name:'beta',game:2}]}},{detail:{team:[{name:'delta',game:0},{name:'echo',game:1},{name:'beta',game:0},{name:'gamma',game:2},{name:'alpha',game:0}]}}];
var result = [],
  map = {};
dataset.forEach(a => {
  a.detail.team.forEach(b => {
    if (!(b.name in map)) {
      map[b.name] = [];
      result.push({
        'label': b.name,
        'data': map[b.name]
      })
    }
    map[b.name].push(b.game);
  });
});
console.log(result);
   

Avoid using reduce or map functions on arrays in this scenario.

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

How to resolve: Preventing Ajax - Post request from executing repetitively

I am facing an issue with a table that is formatted using the Datatables script. There is a column in the table which contains icons for actions. When a user clicks on an icon, a modal is loaded and its content is fetched using the POST method. The modal ...

When the ENTER key is pressed, trigger a function within the form instead of submitting it

Incorporating a table with filterable data utilizing the jQuery DataTables library, I face an issue. The said table is situated within a form where selecting rows (via checkboxes in one column) prompts the SUBMIT button to add them to a collection. The ta ...

Switch Between Different Background Colors for Table Rows With Each Click

This script changes colors when a row in a specific column is clicked: $(document).ready(function(){ $("#rowClick").children("tbody").children("tr").children("td").click(function(){ $(this.parentNode).toggleClass("enroute"); }); }); CSS: .placed{ b ...

Using React Native with TypeScript to Select the Parent and Child Checkboxes within a FlatList

My objective is to ensure that when a user selects a checkbox for one of the parent items ('Non Veg Biryanis', 'Pizzas', 'Drinks', 'Desserts') in the flatlist, all corresponding child items should also be selected au ...

Developing a new class within a function

In this section of the HTML file, I have set up a form to collect email and password information from new users in order to create a new profile: <form name="userInfo"> <fieldset> <legend>Create a new account</legend> ...

The callback function in AngularJS filters

I'm currently using an AngularJS filter to sort through a list of items. Here is the Jade markup I am using: li(ng-repeat="parcel in parcels | filter : filterActiveAreaParcels") After the filter function runs and the elements are displayed in the DO ...

Ways to extract data from a chosen radio button choice

Excuse me, I have a form with an input field and radio buttons. Can someone please help me with how to retrieve the value of the selected radio button and then populate that value into the input text field? For reference, here is the link to the jsfiddle: ...

proper integration of socket.io

I have been experimenting with socket io for my project to display online friends, and I have noticed an issue that seems strange to me. Every time the page is rerendered (whether due to a user changing their profile information or sending a friend request ...

Incorporate data from a CSV file into an HTML table on the fly with JavaScript/jQuery

I have a CSV file that is generated dynamically by another vendor and I need to display it in an HTML table on my website. The challenge is that I must manipulate the data from the CSV to show corrected values in the table, only displaying products and not ...

Error: An unexpected identifier was found within the public players code, causing a SyntaxError

As a newcomer to jasmine and test cases, I am endeavoring to create test cases for my JavaScript code in fiddle. However, I'm encountering an error: Uncaught SyntaxError: Unexpected identifier Could you guide me on how to rectify this issue? Below is ...

Using postMessage to communicate with the localstorage of an iframe from a separate domain

I have a question regarding the challenges of using localStorage for performance reasons and any potential workarounds. From what I gather, once a reference to localStorage is detected on a page (at compile time?), it blocks the thread to read data from di ...

Navigating to the most recent item within ng-repeat (AngularJS or JavaScript)

I am working on a feature where posts are displayed using ng-repeat in a div, and users can enter new posts in an input box. The posts are sorted so that the latest one appears at the bottom. After adding a new post, I want to automatically scroll down t ...

Using the className prop in a React Component

Struggling to assign a classname to the material-ui Button component. Here are my failed attempts: Attempt 1: attributes.map((attribute, index) => { const classString = 'classes.button' + index; console.log(classString) return ( &l ...

Enhancing the Syntax of If and If Else in Jquery Functions

I'm struggling to simplify and optimize this block of code. Would appreciate any help in making it more efficient! var status = "closed"; $(document).on('click', '[data-toggle-nav]', function(event) { if ($(this) && status = ...

JavaScript - splitting numbers into multiple parts

Need help with a JavaScript question regarding numbers like 2,5 or 2.5 I attempted to perform a multi-split operation using the following code: '2.5'.split(/,|./) However, it resulted in an incorrect output: ["", "", "", ""] ...

Determine if the start_date is greater than the end_date using jQuery

Having a particular issue with date validation. The start_date and end_date are obtained from an HTML form, being chosen using a bootstrap date picker. A sample of the dates looks like this: start_date = 15-06-2016 end_date = 14-06-2016 To verify if th ...

Can you provide a database of words for different cities, towns, and countries in MongoDB (or in JSON

Currently, I am in the process of developing an application that utilizes MongoDB. One specific feature I am working on implementing is an 'auto-suggest' functionality on the front-end. For example, as a user begins to type the first few letters ...

What is the best way to eliminate the hash from the URL of a single-route Angular application without the need for ui.router?

I came across a question that has been asked before on Stack Overflow, but unfortunately, it remains unanswered and without any comments. In my Angular app, I am working with a single route and I want to find a way to eliminate the # from the URL. If I h ...

What could be causing the lack of response from PHP Ajax?

In the midst of tackling my college project, I find myself working on a webpage that is designed to showcase City and temperature information. To accomplish this task, I am delving into the realm of AJAX in order to dynamically update the temperature at sp ...

Populating a form field using another input

I am facing an issue with retrieving the price of a product in one field when the product name is selected in another field on a simple POS system. It works fine for the first product, but when I add another row for the next product, the price does not dis ...