Transform JSON structure (Group data)

Here is the JSON object I am working with:

[{
    "name" : "cat",
    "value" : 17,
    "group" : "animal",
},
 {
    "name" : "dog",
    "value" : 6,
    "group" : "animal",
},
 {
    "name" : "snak",
    "value" : 2,
    "group" : "animal",
},
{
    "name" : "tesla",
    "value" : 11,
    "group" : "car",
},
{
    "name" : "bmw",
    "value" : 23,
    "group" : "car",
}]

I am trying to transform this JSON into the following format using JavaScript:

[{
  "name":"animal",
  "children":[
     {"name":"cat", "value":17},
     {"name":"dog", "value":6},
     {"name":"snak", "value":2}
]},
{
  "name":"car",
  "children":[
     {"name":"bmw", "value":11},
     {"name":"tesla", "value":23}
]}]

I attempted to achieve this conversion and filtering using the Reduce function, but I was unable to get it in the desired format.

EDIT:

The code snippet I tested for this purpose is as follows:

let groupBy = function(xs, key) {
    return xs.reduce(function(rv, x) {
    (rv[x[key]] = rv[x[key]] || []).push(x);
    return rv;
    }, {});
};

let groubedByExchange=groupBy(JSON_data, 'group');

Answer №1

One way to solve this problem is by creating an array and then searching for elements with the same group in the array.

var array = [{ name: "cat", value: 17, group: "animal" }, { name: "dog", value: 6, group: "animal" }, { name: "snake", value: 2, group: "animal" }, { name: "tesla", value: 11, group: "car" }, { name: "bmw", value: 23, group: "car" }],
    result = array.reduce((r, { group: name, ...object }) => {
        var temp = r.find(o => o.name === name);
        if (!temp) r.push(temp = { name, children: [] });
        temp.children.push(object);
        return r;
    }, []);
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Answer №2

An effective approach involves creating an intermediary dictionary and then converting it to the desired output structure.

To achieve this, you can utilize Array.reduce(), Object.entries(), and Array.map() as demonstrated below:

const data = [
  { "name" : "cat", "value" : 17, "group" : "animal" },
  { "name" : "dog", "value" : 6, "group" : "animal" },
  { "name" : "snak", "value" : 2, "group" : "animal" },
  { "name" : "tesla", "value" : 11, "group" : "car" },
  { "name" : "bmw", "value" : 23, "group" : "car" }
];

const result = Object.entries(data.reduce((acc, { name, value, group }) => {
  acc[group] = (acc[group] || []);
  acc[group].push({ name, value });
  return acc;
}, {})).map(([key, value]) => ({ name: key, children: value }));

console.log(result);

The use of spread operator allows for a more concise code without compromising readability:

const data = [
  { "name" : "cat", "value" : 17, "group" : "animal" },
  { "name" : "dog", "value" : 6, "group" : "animal" },
  { "name" : "snak", "value" : 2, "group" : "animal" },
  { "name" : "tesla", "value" : 11, "group" : "car" },
  { "name" : "bmw", "value" : 23, "group" : "car" }
];

const result = Object.entries(data.reduce((acc, { name, value, group }) => {
  acc[group] = [...(acc[group] || []), { name, value }];
  return acc;
}, {})).map(([key, value]) => ({ name: key, children: value }));

console.log(result);

A further optimization using the comma operator results in even shorter code:

const data = [
  { "name" : "cat", "value" : 17, "group" : "animal" },
  { "name" : "dog", "value" : 6, "group" : "animal" },
  { "name" : "snak", "value" : 2, "group" : "animal" },
  { "name" : "tesla", "value" : 11, "group" : "car" },
  { "name" : "bmw", "value" : 23, "group" : "car" }
];

const result = Object.entries(data.reduce((acc, { name, value, group }) =>
  (acc[group] = [...(acc[group] || []), { name, value }], acc)
, {})).map(([key, value]) => ({ name: key, children: value }));

console.log(result);

Additionally, the same outcome can be achieved using Object.assign():

const data = [
  { "name" : "cat", "value" : 17, "group" : "animal" },
  { "name" : "dog", "value" : 6, "group" : "animal" },
  { "name" : "snak", "value" : 2, "group" : "animal" },
  { "name" : "tesla", "value" : 11, "group" : "car" },
  { "name" : "bmw", "value" : 23, "group" : "car" }
];

const result = Object.entries(data.reduce((acc, { name, value, group }) =>
  Object.assign(acc, { [group]: [...(acc[group] || []), { name, value }] })
, {})).map(([key, value]) => ({ name: key, children: value }));

console.log(result);

Finally, there's a slightly longer but reusable implementation with a groupBy function:

const data = [
  { "name" : "cat", "value" : 17, "group" : "animal" },
  { "name" : "dog", "value" : 6, "group" : "animal" },
  { "name" : "snak", "value" : 2, "group" : "animal" },
  { "name" : "tesla", "value" : 11, "group" : "car" },
  { "name" : "bmw", "value" : 23, "group" : "car" }
];

const groupBy = prop => data => {
  return data.reduce((dict, item) => {
    const { [prop]: _, ...rest } = item;
    dict[item[prop]] = [...(dict[item[prop]] || []), rest];
    return dict;
  }, {});
};

const result = Object.entries(groupBy('group')(data))
  .map(([key, value]) => ({ name: key, children: value }));

console.log(result);

Answer №3

Utilizing Array#from, Array#reduce, Array#concat, destructuring, spread syntax along with the Map object.

  1. Reconfigure your data structure using a Map
  2. Restructure your data by utilizing .map

const information=[{"name":"cat","value":17,"group":"animal",},{"name":"dog","value":6,"group":"animal",},{"name":"snak","value":2,"group":"animal",},{"name":"tesla","value":11,"group":"car",},{"name":"bmw","value":23,"group":"car",}];

const result = Array.from(
  information.reduce((accumulator,{group, ...others})=>{
    return accumulator.set(group, [others].concat(accumulator.get(group)||[]));
  }, new Map())
).map(([group, children])=>({group,children}));

console.log(result);

Answer №4

const items = [{
    "name": "apple",
    "quantity": 5,
    "type": "fruit",
  },
  {
    "name": "banana",
    "quantity": 8,
    "type": "fruit",
  },
  {
    "name": "carrot",
    "quantity": 3,
    "type": "vegetable",
  },
  {
    "name": "pepper",
    "quantity": 6,
    "type": "vegetable",
  }
]

const organizedItems = items.reduce((prev, current) => {
  const type = prev.find(itemType => itemType.name === current.type)
  if (type) {
    type.items.push({
      name: current.name,
      quantity: current.quantity
    })
    return prev
  }

  const newType = {
    name: current.type,
    items: [{
      name: current.name,
      quantity: current.quantity
    }]
  }
  prev.push(newType)
  return prev
}, [])

console.log(organizedItems)

Here is an example. You first attempt to locate the specified group in the updated array. If it is found, you append the child element to it. If not, a new group with a children array is created and added to the array.

Answer №5

Here is a solution using the lodash library:

var data = [{
    "name": "cat",
    "value": 17,
    "group": "animal",
  },
  {
    "name": "dog",
    "value": 6,
    "group": "animal",
  },
  {
    "name": "snake",
    "value": 2,
    "group": "animal",
  },
  {
    "name": "tesla",
    "value": 11,
    "group": "car",
  },
  {
    "name": "bmw",
    "value": 23,
    "group": "car",
  }
]

var result = _(data)
  .groupBy('group')
  .map((group, name) =>
    ({
      name,
      children: _.map(group, ({
        name: name,
        value
      }) => ({
        name,
        value
      }))
    }))
  .value()

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Answer №6

Here is my ES6 solution utilizing map and reduce:

const data = [
  {
    name: "cat",
    value: 17,
    group: "animal"
  },
  {
    name: "dog",
    value: 6,
    group: "animal"
  },
  {
    name: "snak",
    value: 2,
    group: "animal"
  },
  {
    name: "tesla",
    value: 11,
    group: "car"
  },
  {
    name: "bmw",
    value: 23,
    group: "car"
  }
];

const grouped = data.reduce((acc, currItem) => {
  const groupKey = currItem.group;
  if (!acc[groupKey]) {
    acc[groupKey] = [currItem];
  } else {
    acc[groupKey].push(currItem);
  }
  return acc;
}, {});

const res = Object.keys(grouped).map(key => ({
  name: key,
  children: grouped[key].map(groupItem => ({
    name: groupItem.name,
    value: groupItem.value
  }))
}));

console.log(res);

View the console output to observe the results as the code progresses.

I believe some other responses make use of an unnecessary find() method (which has a time complexity of O(n)), whereas you can simply check if a current group key already exists in O(1).

I have opted to store the grouped outcomes in an intermediate variable grouped for clarity purposes, but it is possible to consolidate everything.

Answer №7

function groupThings(things) {
  return things.reduce((acc, { name, value, group }) => {
    const existingGroup = acc.find(g => g.name === group) || {};
    return [
      ...acc.filter(g => g.name !== group),
      {
        ...existingGroup,
        name: group,
        children: [...(existingGroup.children || []), { name, value }],
      },
    ];
  }, []);
}

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

I want to save the information for "KEY" and "textValue" in JSON format and then return it as a response when I make a request to app.get("/api"). How can I achieve this?

Working with GCP Document AI using Node.js and react.js, I have created a JSON structure (var jsonResult) in the provided code. In the for loop, I am extracting key and text value data by using console.log(key); and console.log(textValue);. However, my g ...

Populating fields in a new AngularJS document from a table

I have a project where there is a table displaying different instances of our service, and each row has an info button that opens a form with the corresponding row's information autofilled. However, I am facing an issue where by the time I retrieve th ...

Retrieving JavaScript array data following a page reload

I am facing an issue with updating an array dynamically in my C# server-side code and then utilizing the updated data in a JQuery function on my webpage. When the page first loads, the array is filled with some default values by C#. However, when a user ma ...

Send data in JSON format along with an identifier using Jquery AJAX

I am having trouble sending JSON data along with 2 IDs using a jQuery AJAX post. Despite my efforts, I can't seem to get it working. Here is the code snippet in question: try { var surveyID = localStorage.getItem("surveyId"); var userDetails ...

Populate a select list in real time with dynamically generated options

I'm facing a challenge at the moment; I am using JavaScript to dynamically generate select boxes, however, I require Ajax to populate them with options. At the moment, my code is returning undefined and I am unsure of how to proceed. While my PHP succ ...

Waveform rendering in HTML5 using wavesurfer.js struggles to handle large mp3 files

Recently, I was considering incorporating wavesurfer.js into one of my projects so I decided to explore the demo on To test it out, I uploaded a large mp3 file (approximately 2 hours long) onto the designated area in the middle of the page. It appeared to ...

Struggling to create a C# class structure for a JSON string

Currently, I am faced with the challenge of deserializing an object into a custom class. The string that will be passed to me has the following format: {nodename:"node1", version:"v1", PARM1:"p1", PARM2:"p2" ,…, PARAMN:"pn"}. From what I understand, I ...

What is the method for retrieving an array or object that contains a collection of files designated for uploading within the jQuery file upload plugin?

Currently, I have successfully integrated a form into my Rails site and set up the jQuery file upload plugin. The upload form functions properly with the ability to select multiple files and utilize all ajax upload features. However, a challenge I am faci ...

update value asynchronously

My implementation involves a dialog controller: .controller('loadingDialogCtrl', function($scope, $mdDialog, $rootScope, loadingDialog) { $scope.loadingDialog = loadingDialog; }); In another controller, I use the dialog controller and manip ...

Can we utilize conditions to both select and deselect items using JavaScript and PHP together?

I have a selection list with checkboxes that is dynamically generated based on certain conditions in the code snippet below. if ($data_inteiro_01 <= $data_inteiro_02) { if ($parcela[$i] === 0) { $display = 'disabled'; } } els ...

Quickest method for sorting an array of objects based on the property of another object's array

Within my code, I have two arrays of objects, both containing a "columnId" property. My goal is to rearrange the first array to match the order of the second. I attempted the following method: filtered = visibleColumns.filter(function(v) { re ...

Determine using Lodash whether there is an object in an array that matches the ID from a separate array

There is a user array defined as follows: var users = [{ id: 1, name: 'ABC', isDisplay: true }, { id: 2, name: 'XYZ', isDisplay: true }, { id: 3, name: 'JKL', isDisplay: true }]; Additionally, there is another arra ...

Transforming React-Leaflet Popup into a custom component: A step-by-step guide

Currently working on a project where I am utilizing both React-Leaflet and Material-UI by callemall. The challenge I am facing involves trying to incorporate the Material-UI Card component within the <Popup></Popup> component of React-Leaflet. ...

Designing an interactive header interface using React and Material UI

My header.jsx file contains the following code: // Default Import Statements var Login = require(login.jsx) const HeaderComponent = React.createClass({ getInitialState () { return { loggedIn: false, }; }, render() { return ( ...

Utilize filters on a dataset to display specific information

Front-end: const [filters, setFilters] = useState({ type: "", country:"", }); const onChangeFilterType = e => { const workingObject = {...filters}; workingObject.type = e.target.value; setFilters(workingObject); }; ...

HTML Tutorial: A Beginner's Guide to Invoking REST API

Hi there! I'm new to APIs and struggling to grasp the concept. The tutorials online seem more complex than necessary. Here's what I need help with: I want to create a basic webpage that allows me to search for information using the Pokemon API a ...

Utilizing Dynamic Image Sources in Vue.js with the Help of APIs

Can someone help me figure out how to solve this issue? I have an API that returns a base64 image, and I want to load this image on my site. Any suggestions on where or how I should implement my function? This is the API call located in the methods: metho ...

jquery activating the toggle function to switch between child elements

I'm facing a challenge where I can't use .children() in this scenario, as it won't work since the elements aren't technically children. Here's the snippet of HTML that I'm working with: <p class="l1">A</p> ...

Creating a specialized pathway with variable inputs within the URL

As a Node beginner, I am facing a challenge with an Express exercise on dynamic routes. The task at hand is to create a route that can accept dynamic arguments in the URL path and respond with a quote from the respective author. Here's a snippet of th ...

Transformation from a class component to a function component in React JS

I have a class component that I need to convert into a functional component. So, I started by refactoring the constructor. Below is the original class component: class EventCalendar extends React.Component { constructor(props) { super(props) ...