How to convert deeply nested object structures containing arrays in JavaScript

Despite the less-than-desirable name of this inquiry, the question is fairly straightforward. I have a particular object:

let test = {
  date1: [
    {
      time: 1,
      value: 5,
    },
    {
      time: 2,
      value: 6,
    },
  ],
  date2: [
    {
      time: 1,
      value: 20,
    },
    {
      time: 2,
      value: 10,
    },
  ],
};

I am looking to reformat it into something like this:

let result = {
  date1: {
    values: [5, 6],
    times: [1, 2],
  },
  date2: {
    values: [1, 2], // perhaps easier for summarization?!
    times: [10, 20],
  },
};

I am aiming to summarize the value data for each date. The idea is that having them in an array will simplify the summarization process. While aware of alternative methods (and open to exploring them), my current approach is falling short of my expectations. Here's what I have at the moment:

let keys = Object.keys(test);
let red = keys.reduce((acc, curr) => {
  return (acc[curr] = test[curr].map((e) => e.value));
}, {});

console.log(`red: `, red);

However, its output is as follows:

red: [ 20, 10 ]

Answer №1

This

return (acc[curr] = test[curr].map((e) => e.value));

is the same as

acc[curr] = test[curr].map((e) => e.value);
return acc[curr];

accessing a nested key of the accumulator during each iteration - this is not the desired logic. To prevent previously assigned values from being lost and to account for both the time and value properties of the array being iterated over, you need to return the entire accumulator on a separate line. Additionally, your => e.value only extracts one of the two properties you require.

let test = {
  date1: [
    {
      time: 1,
      value: 5,
    },
    {
      time: 2,
      value: 6,
    },
  ],
  date2: [
    {
      time: 1,
      value: 20,
    },
    {
      time: 2,
      value: 10,
    },
  ],
};

const keys = Object.keys(test);
const result = keys.reduce((acc, key) => {
  acc[key] = {
    values: test[key].map(({ value }) => value),
    times: test[key].map(({ time }) => time),
  };
  return acc;
  return acc;
}, {});

console.log(result);

or alternatively

let test = {
  date1: [
    {
      time: 1,
      value: 5,
    },
    {
      time: 2,
      value: 6,
    },
  ],
  date2: [
    {
      time: 1,
      value: 20,
    },
    {
      time: 2,
      value: 10,
    },
  ],
};

const result = Object.fromEntries(
  Object.entries(test).map(([key, arr]) => [
    key,
    {
      values: arr.map(({ value }) => value),
      times: arr.map(({ time }) => time),
    }
  ])
);
console.log(result);

Answer №2

Here's a slight variation you could try out:

const transformedData = Object.keys(data).reduce((acc, key) => {
        data[key].forEach((item) => {
            acc.push({
            date: key,
            time: item.time,
            value: item.value,
            });
        });
        return acc;
    }, []);
    console.log(transformedData);

Answer №3

If all the inner objects share the same keys and there are no empty date arrays:

const sampleData = {date1:[{time:1,value:5},{time:2,value:6},],date2:[{time:1,value:20},{time:2,value:10},]};

let dates = Object.keys(sampleData);
let transformedData = dates.reduce((acc, current) => ({
  ...acc,
  [current]: Object.keys(sampleData[current][0])
                .reduce((acc, key) => ({
                  ...acc,
                  [key + 's']: sampleData[current].map(obj => obj[key])
                }), {})
}), {});

console.log(`Transformed data: `, transformedData);

Answer №4

If you're looking to sum up values from different objects without the need for creating arrays first, there's a more efficient approach you can take. Here's what your end result might look like:

{
  date1: 11,
  date2: 30
}

While using reduce is a good start for summing up values, you can further enhance your code by incorporating Object.entries and Object.fromEntries. This will enable you to create the desired object structure more effectively:

const test = {date1: [{time: 1,value: 5,},{time: 2,value: 6,},],date2: [{time: 1,value: 20,},{time: 2,value: 10,},],};

const result = Object.fromEntries(
    Object.entries(test).map(([key, arr]) => 
        [key, arr.reduce((sum, {value}) => sum + value, 0)]
    )
);

console.log(result);

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

Hide the selection box when hovering over the Div

Looking for a quick solution. I want the option drop down to close when another div element is hovered over. First, open the drop down and hover over the red element on the right side. When hovering over the red element, I would like the drop down to clos ...

Using Java beans to present form data utilizing session

How can I utilize Java Beans and session beans to store user input data and display a preview of the entered details on the next page? I have already created a servlet using JSP, but now I want to incorporate Java Beans to showcase the form data. How shoul ...

What method can I use to ensure that the sidebar stays fixed at a particular div as the user continues to scroll down the

Is there a way to automatically fix the sidebar once the user scrolls down and hits the top of the .Section2? Currently, I have to manually enter a threshold number which can be problematic due to varying positions across browsers and systems. Fiddle htt ...

Is there a workaround using jQuery to enable CSS3 functionality across all browsers?

Is there a way in jQuery to make all browsers act as if they have CSS3 capabilities? ...

Error Encountered While Creating a Polygon Wallet on Fireblocks

After following the instructions from Fireblocks Docs, I successfully created a default wallet named "BTC_TEST" like this: enter image description here. However, when attempting to create a Matic wallet, I encountered an Axios Error. Despite Matic being a ...

Is there a way to retrieve the headers from an HTTP response in JavaScript that wasn't initiated by an AJAX request?

I have a login page setup to send an HTTP post request to the server, which then redirects me to another page on the server in the response message. On this new page, I need to access the location header to obtain a specific value for future server tasks. ...

submitting URL from dropdown menu without using the 'submit' button

My situation involves a dropdown list: @Html.DropDownList("InnerId", Model.GroupDropDownList, new { @class = "select_change" }) I am looking to achieve submitting the value when a user clicks on the selection without needing to select and then use a subm ...

Guide on how to switch a class on the body using React's onClick event

There's a button in my code that triggers the display of a modal-like div element. When this button is clicked, I aim to apply a class to the body element; then when the close button is clicked, I'll remove this class. I'm looking for guid ...

Enhancing Typography in Material UI with Custom Breakpoints in React CustomThemes

Currently, I am utilizing material UI and React to develop a single-page application (SPA). However, I have encountered an issue with ensuring that my pages are responsive for smaller screen sizes. To address this, I have been manually adding fontSize: { x ...

What is the best way to remove a specific item from a list of maps in DynamoDB based on a particular attribute value within the

Below is an example of a list I have: { "favorites": [ { "createdAt": 1448998673852, "entityId": "558da3de395b1aee2d6b7d2b", "type": "media" }, { "createdAt": 1448998789252, "entityId": "558da3de395b1aee2d6b7d83 ...

The Chrome file storage system saves information in files

My challenge is to save data obtained from the Chrome geolocation API into a text file using the Chrome fileSystem API. However, despite successfully creating a file, it remains empty after the process. To simplify, I attempted to add the string '1234 ...

Investigate the presence of a vertical scrollbar using JQuery or JavaScript

Within an HTML report, I have applied the style "overflow:auto" to allow for dynamic data filling. I am now facing the challenge of detecting whether a vertical scrollbar exists within the report. After scouring various forums for solutions, I came across ...

Create an Array with a dynamic name derived from the values of other variables

In my JavaScript project, I am facing a challenge in naming arrays based on dynamic data such as room numbers and user IDs. As the rooms and users are constantly changing, I need to create multiple arrays accordingly. Although this code is incorrect, it s ...

Numerous instances of Codemirror

I have the ability to generate and exhibit multiple dynamic codemirror instances, however, I am having trouble referencing them using the code snippet below. I suspect that the problem lies in creating a dynamic function name (not entirely sure how to ac ...

I'm having trouble getting this angular expression to cooperate in Plunker. Can anyone shed some light on why {{ 843 / 42

I'm currently diving into Angular with the help of Plural Sight. The initial lesson dives into utilizing the ng-app directive. For those interested, here's a direct link to the Plunker editor: http://plnkr.co/edit/HIDCS8A9CR1jnAIDR0Zb?p=preview ...

Utilize an imported function within a React component's return statement to avoid an invalid hook call issue

Hey everyone, I've created a reusable component that can translate keys into a chosen language using keynames as strings or variables. Typically, I would use a <t> tag for this purpose, but due to certain reasons, I am replacing current transl ...

Executing API call utilizing the Request module within a node.js application

In my node.js app, I have a request call that looks like this: request({ url:chanURL, qs:chanProperties}, function(err, response, body) { if(err) { console.log(err); return; } body = JSON.parse(body); (function (body) { Objec ...

Obtaining the attribute value of a disabled element in an Angular JS application

Currently, I am struggling to retrieve the attribute value of a disabled element during runtime and then assert its value. The code I'm using is not providing the desired result: softAssert.assertFalse(shrSub.nextButton().waitForPresent().getAttribu ...

transmitting error messages from a service to a controller in AngularJS

Controller.js var vm = this; vm.admin = {}; vm.add = function () { API.addAdmin(token, vm.admin) .then(function (resp) { vm.hideForm = true; vm.showButton = true; Notify.green(resp); }, function (re ...

Encountered an Error: Trying to use a function that is undefined - While utilizing Jquery Tabs

Working on implementing Jquery Tabs using the "description" and "reviews" li tags as tabs. Testing it out here . Everything seems to be functioning correctly here Key Points: This is Wordpress Multi-Site setup. The issue occurs in certain folders or "si ...