Combining and grouping objects in JavaScript using ES5

I have an object structured like the following:

{
"User 1":[
{"count":"1","stage":"A","jCount":"10","name":"User 1","stageId":"A1"},
{"count":"8","stage":"B","jCount":"10","name":"User 1","stageId":"B1"},
],

"User 2":[
{"count":"7","stage":"C","jCount":"8","name":"User 2","stageId":"C1"},
{"count":"8","stage":"B","jCount":"8","name":"User 2","stageId":"B1"},
{"count":"9","stage":"A","jCount":"8","name":"User 2","stageId":"A1"},
{"count":"8","stage":"D","jCount":"8","name":"User 2","stageId":"D1"},
],

"User 3":[
{"count":"6","stage":"D","jCount":"6","name":"User 3","stageId":"D1"},
{"count":"8","stage":"B","jCount":"6","name":"User 3","stageId":"B1"},
{"count":"1","stage":"A","jCount":"6","name":"User 3","stageId":"A1"},
],
/* Many more users */
}

I am attempting to transform my object into this format:

[
{
"name":"User 1",
"jCount":10,
"stageIdCountA1":1,
"stageIdCountB1":8,
"stageIdCountC1":0,
"stageIdCountD1":0,
},{
"name":"User 2",
"jCount":8,
"stageIdCountA1":9,
"stageIdCountB1":8,
"stageIdCountC1":7,
"stageIdCountD1":8,
},{
"name":"User 3",
"jCount":6,
"stageIdCountA1":1,
"stageIdCountB1":8,
"stageIdCountC1":0,
"stageIdCountD1":6,
},
/* Many more users */
]

There are a maximum of 4 stages: A1,B1,C1,D1 and jCount is common in the child objects of the user array.

If there is no stage, it should be represented as 0.

I attempted to manipulate this in an AngularJS view but found it challenging.

Answer №1

To transform each user object into an array item, utilize the map function, and nest reduce within the map function to consolidate the stages array into a single object:

const input={"User 1":[{"count":"1","stage":"A","jCount":"10","name":"User 1","stageId":"A1"},{"count":"8","stage":"B","jCount":"10","name":"User 1","stageId":"B1"},],"User 2":[{"count":"7","stage":"C","jCount":"8","name":"User 2","stageId":"C1"},{"count":"8","stage":"B","jCount":"8","name":"User 2","stageId":"B1"},{"count":"9","stage":"A","jCount":"8","name":"User 2","stageId":"A1"},{"count":"8","stage":"D","jCount":"8","name":"User 2","stageId":"D1"},],"User 3":[{"count":"6","stage":"D","jCount":"6","name":"User 3","stageId":"D1"},{"count":"8","stage":"B","jCount":"6","name":"User 3","stageId":"B1"},{"count":"1","stage":"A","jCount":"6","name":"User 3","stageId":"A1"},],};

const stages = ['A', 'B', 'C', 'D'];
const output = Object.entries(input).map(([name, arr]) => {
  const { jCount } = arr[0];
  const stageCounts = stages.reduce((a, stageName) => {
    const propName = 'stageIdCount' + stageName;
    const foundStage = arr.find(({ stage }) => stageName === stage);
    const count = foundStage ? foundStage.count : 0;
    a[propName] = count;
    return a;
  }, {});
  return { name, jCount, ...stageCounts };
});
console.log(output);

If you are unable to incorporate spread syntax (although recommended), substitute

return { name, jCount, ...stageCounts };

with

return Object.assign({ name, jCount }, stageCounts);

Answer №2

Incorporating ES6 with the usage of Object.entries, you have the ability to achieve something similar to this:

const obj = {
  'User 1': [
{ count: '1', stage: 'A', jCount: '10', name: 'User 1', stageId: 'A1' },
{ count: '8', stage: 'B', jCount: '10', name: 'User 1', stageId: 'B1' }
  ],

  'User 2': [
{ count: '7', stage: 'C', jCount: '8', name: 'User 2', stageId: 'C1' },
{ count: '8', stage: 'B', jCount: '8', name: 'User 2', stageId: 'B1' },
{ count: '9', stage: 'A', jCount: '8', name: 'User 2', stageId: 'A1' },
{ count: '8', stage: 'D', jCount: '8', name: 'User 2', stageId: 'D1' }
  ],

  'User 3': [
{ count: '6', stage: 'D', jCount: '6', name: 'User 3', stageId: 'D1' },
{ count: '8', stage: 'B', jCount: '6', name: 'User 3', stageId: 'B1' },
{ count: '1', stage: 'A', jCount: '6', name: 'User 3', stageId: 'A1' }
  ]
  /* Numerous other users */
};

const stages = ['A1', 'B1', 'C1', 'D1'];

const getCount = (stage, user) => {
  const stageItem = obj[user.name].find(s => s.stageId === stage);
  return stageItem ? stageItem.count : 0;
};

const r = Object.entries(obj)
  .map(([name, user]) => ({ name, jCount: user[0].jCount }))
  .map(user => {
const stagesCounts = stages
  .map(stage => ({
    [`stageIdCount${stage}`]: getCount(stage, user)
  }))
  .reduce((acc, stage) => ({ ...acc, ...stage }), {});
return { ...user, ...stagesCounts };
  });

console.log(r);

Update (ES5)

const obj = {
  'User 1': [
    { count: '1', stage: 'A', jCount: '10', name: 'User 1', stageId: 'A1' },
    { count: '8', stage: 'B', jCount: '10', name: 'User 1', stageId: 'B1' }
  ],

  'User 2': [
    { count: '7', stage: 'C', jCount: '8', name: 'User 2', stageId: 'C1' },
    { count: '8', stage: 'B', jCount: '8', name: 'User 2', stageId: 'B1' },
    { count: '9', stage: 'A', jCount: '8', name: 'User 2', stageId: 'A1' },
    { count: '8', stage: 'D', jCount: '8', name: 'User 2', stageId: 'D1' }
  ],

  'User 3': [
    { count: '6', stage: 'D', jCount: '6', name: 'User 3', stageId: 'D1' },
    { count: '8', stage: 'B', jCount: '6', name: 'User 3', stageId: 'B1' },
    { count: '1', stage: 'A', jCount: '6', name: 'User 3', stageId: 'A1' }
  ]
  /* Many more users */
};

const stages = ['A1', 'B1', 'C1', 'D1'];

function getCount(stage, user) {
  const stageItem = obj[user.name].find(s => s.stageId === stage);
  return stageItem ? stageItem.count : 0;
}

function mapStages(user) {
  return stages
    .map(stage => ({
      [`stageIdCount${stage}`]: getCount(stage, user)
    }))
    .reduce((acc, stage) => ({ ...acc, ...stage }), {});
}

const r = Object.entries(obj)
  .map(function(entry) {
    return { name: entry[0], jCount: entry[1][0].jCount };
  })
  .map(function(user) {
    return Object.assign(user, mapStages(user));
  });

console.log(r);

Answer №3

Here is the process I followed to discover my solution:

var obj = {
'User 1': [
{ count: '1', stage: 'A', jCount: '10', name: 'User 1', stageId: 'A1' },
{ count: '8', stage: 'B', jCount: '10', name: 'User 1', stageId: 'B1' }
],

'User 2': [
{ count: '7', stage: 'C', jCount: '8', name: 'User 2', stageId: 'C1' },
{ count: '8', stage: 'B', jCount: '8', name: 'User 2', stageId: 'B1' },
{ count: '9', stage: 'A', jCount: '8', name: 'User 2', stageId: 'A1' },
{ count: '8', stage: 'D', jCount: '8', name: 'User 2', stageId: 'D1' }
],

'User 3': [
{ count: '6', stage: 'D', jCount: '6', name: 'User 3', stageId: 'D1' },
{ count: '8', stage: 'B', jCount: '6', name: 'User 3', stageId: 'B1' },
{ count: '1', stage: 'A', jCount: '6', name: 'User 3', stageId: 'A1' }
]
/* More users can be added */
};

var stages = ['A1', 'B1', 'C1', 'D1'];

function getCount(stage, user) {
var stageItem = obj[user.name].find(function(s) {
return s.stageId === stage;
});
return (stageItem ? stageItem.count : 0);
}

var _extends = Object.assign || function(target) { 
for (var i = 1; i < arguments.length; i++) { 
var source = arguments[i]; 
for (var key in source) { 
if (Object.prototype.hasOwnProperty.call(source, key)) { 
target[key] = source[key]; 
} 
} 
} 
return target; 
};

function _defineProperty(obj, key, value) { 
if (key in obj) { 
Object.defineProperty(obj, key, { 
value: value, enumerable: true, configurable: true, writable:
true }); 
} else { 
obj[key] = value; 
} 
return obj; 
}

function mapStages(user) {
return stages.map(function(stage) {
return _defineProperty({}, "stageIdCount" + stage, getCount(stage, user));
}).reduce(function(acc, stage) {
return _extends({}, acc, stage);
}, {});
}

var r = Object.entries(obj)
.map(function(entry) {
return { name: entry[0], jCount: entry[1][0].jCount };
})
.map(function(user) {
return Object.assign(user, mapStages(user));
});

console.log(r);

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

Tips on obtaining standardized values for an array with ng-repeat

My goal is to retrieve the normalized value of an array associated with different groups without altering the original array items. Instead, I am creating new objects for each group's normalized items. http://jsfiddle.net/k5Dvj/5/ $scope.nomalizedIt ...

Error 404 encountered while attempting to view HTML Page on FLASK server - unable to display content

I am facing an issue with my Flask project. I can browse to my main page, index.html, but when I click a button on the index page that directs me to mytopo.html, the page loads without showing the desired topology view and I encounter an error. The error m ...

Guide to transforming a character array into a character pointer in the C programming language

I am facing an issue with passing a character array to a function that expects a character pointer. The code works fine when I directly pass the array, but when I try to create an array or a pointer from it, a segmentation fault occurs. This snippet of co ...

What is the reason behind not requiring to invoke the next function in a Sails.js controller method, even when it includes an asynchronous database query?

Sample controller function: fetchArticles: function(req, res) { Articles.find({}).exec(function(err, articles) { res.json(articles) // It appears this part is asynchronous // Is next() required here? }) } In my experience, I typicall ...

Having trouble generating a JSON file from user input upon clicking the button in a C# Windows Form application

Currently, I am in the process of developing a C# application using VS2017 windows form application. The primary functionality of this app is to take user input and save it into a JSON file. However, there's a limitation where only one user input can ...

The search and sorting functionality in jquery DataTables is malfunctioning

I am facing difficulties with sorting and filtering the datatable as none of the JS functions seem to be working properly. I have already included the necessary JS files. Here are some details: I am connecting to a database to retrieve data in JSON format. ...

Discover the secrets to replicating the mesmerizing horizontal scrolling menu akin to the

What is the most effective way to create a horizontal menu similar to the innovative Google picture menu? Could someone kindly share their knowledge and provide the code for achieving the same outcome? ...

What is the best way to retrieve an object from the state in my React application?

I have been struggling to locate an item from a collection so that I can update my react component. Despite the fact that the propertyState object is not empty and contains a list that I have successfully console logged, I keep receiving an undefined obj ...

Is there a way to deactivate the minutes input feature in the Angular UI Timepicker?

I am using a plugin that displays the time in hours and minutes. However, I only need to show the hours. Is there a way to hide the minutes block? This is my HTML code: <uib-timepicker ng-model="mytime" ng-change="changed()" hour-step="1" minute-step ...

just require a signature showcased in a specific area

How can you achieve this? Displaying text on a radio as it is selected, ensuring only one option is shown and not revealed to others. https://i.stack.imgur.com/mNyQy.png I have added a red box around the text that should only appear in a specific locatio ...

Laravel relationships and type casting

Currently working on a survey platform where users rate from 0 to 10. I'm testing out using casts to store questions and answers in a single row. Here's a glimpse of how the scores field appears in the database: {"5":8,"6":8} This setup is wor ...

Tips on saving images to a folder and storing the image paths in a database in MEAN stack with the help of Multer

In my collection, I have a set of images with the following structure: { "productId": {type: String}, "imagePaths": {type: Array} } I am trying to upload multiple images and save their respective image paths to the database. After some research, I found ...

Navigating through various JSON arrays using Angular

I am currently working with a large JSON file in Angular and trying to iterate through it. The structure of the JSON file is as follows: { "subject1":[ { "title":"titlehere", "info":"infohere." }], ...

Grouping an array of arrays of objects

I am trying to group an array of objects based on the value of the first item below: const data = [{"value":"value1","metric":1},{"value":"value1","metric":2},{"value":"value3","metric":0},{"value":"value2","metric":4},{"value":"value3","metric":1},{"va ...

Tips for arranging bar series in the NVD3 multibar angularJS directive

I am trying to generate a multi-bar chart using the nvd3 AngularJS directive by cmaurer, but I am facing an issue with stacking some series. Here is the data I am working with: $scope.exampleData = [ { "key": "Initial ...

The server is receiving incorrect exchange rates from Yahoo Finance

My current project involves the use of Node.js, and I have a question regarding the differences between the data sent by Yahoo Finance to the server machine versus a "regular" machine. var http = require('http'); var link = "http://download ...

Generate a random array in PHP only once

How can I randomize an array just once without it rotating multiple times? I am currently using the array_rand() function, but it keeps rotating the array. Here is the code I have been using: <?php $names = array("John","Sarah","Michael"); $ ...

Adding up the numbers with JavaScript

Hello everyone, I've been working on some transformations and now I'm left with an array of objects: Can anyone help me come up with a flexible function that will generate a new object where each data[i] is the sum of values from the previous ob ...

Laravel 5.0 facing issues with AJAX requests

For my Laravel 5.0 project, I am utilizing Google API's for Google Oauth login. After successfully retrieving the email and id_token of the currently logged-in user, I aim to send this data to the SigninController to access our own API. The goal is to ...

How can I ensure that the size of the Dropdown Menu Item matches its parent in both Bootstrap and CSS styles?

I am working on a navigation bar that has a dropdown menu which appears on hover. I want the size of the dropdown menu items to match the size of the parent element. Here is an image for reference: https://i.stack.imgur.com/oNGmZ.png Currently, the "One ...