Generate a fresh array from the existing array and extract various properties to form a child object or sub-array

I am dealing with an array of Responses that contain multiple IDs along with different question answers.

Responses = 
[0:{Id : 1,Name : John, QuestionId :1,Answer :8},
1:{Id : 1,Name : John, QuestionId :2,Answer :9},
2:{Id : 1,Name : John, QuestionId :3,Answer :3},
3:{Id : 1,Name : John, QuestionId :4,Answer :2},
4:{Id : 2,Name : Mark, QuestionId :1,Answer :6},
5:{Id : 2,Name : Mark, QuestionId :2,Answer :2},
6:{Id : 2,Name : Mark, QuestionId :3,Answer :5},
7:{Id : 2,Name : Mark, QuestionId :4,Answer :1}]
----------------------------------------------------------------
Output I want :
 
Arr = 
[0:{Id : 1,Name : John,
 Question : [{QuestionId :1,Answer :9},{QuestionId :2,Answer :8},{QuestionId :3,Answer :3},{QuestionId :4,Answer :2}]},
1:{Id : 2,Name : Mark,
 Question : [{QuestionId :1,Answer :6},{QuestionId :2,Answer :2},{QuestionId :3,Answer :5},{QuestionId :4,Answer :1}]}]
---------------------------------------------------------

I am striving to combine the ID and Name into one array along with a single Question object containing each Question ID paired with its corresponding answer. Despite trying various methods, I have been unsuccessful thus far. Any assistance in this matter would be greatly appreciated. Thank you.

Answer №1

To start, you need to group the data based on the Name field. Once the data is grouped, you can then proceed to map the values. During the mapping process, you have the option to destructure the Id and Name fields of the first question and then map the QuestionId and Answer fields to the Question field.

const groupBy = (arr, key) => arr.reduce((acc, item) => ({
  ...acc,
  [item[key]]: [ ...(acc[[item[key]]] ?? []), item ]
}), {});

const responses = [
  { "Id": 1, "Name": "John", "QuestionId": 1, "Answer": 8 },
  { "Id": 1, "Name": "John", "QuestionId": 2, "Answer": 9 },
  { "Id": 1, "Name": "John", "QuestionId": 3, "Answer": 3 },
  { "Id": 1, "Name": "John", "QuestionId": 4, "Answer": 2 },
  { "Id": 2, "Name": "Mark", "QuestionId": 1, "Answer": 6 },
  { "Id": 2, "Name": "Mark", "QuestionId": 2, "Answer": 2 },
  { "Id": 2, "Name": "Mark", "QuestionId": 3, "Answer": 5 },
  { "Id": 2, "Name": "Mark", "QuestionId": 4, "Answer": 1 }
];

const arr = Object.values(groupBy(responses, 'Name')).map(questions => {
  const [ { Id, Name } ] = questions;
  return {
    Id, Name, Question: questions.map(({ QuestionId, Answer }) =>
      ({ QuestionId, Answer }))
  };
});

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

Alternatively, if you prefer a more direct approach, you can use the reduce function without grouping beforehand. This method may be more tightly coupled but eliminates the need for additional mapping steps.

const reduceBy = (arr, key) => Object.values(arr.reduce((acc, item) => {
  const
    { Id, Name, QuestionId, Answer } = item,
    prev = acc[[item[key]]] || { Id, Name, Question: [] };
  return {
    ...acc,
    [item[key]]: {
      ...prev,
      Question: [ ...prev.Question, { QuestionId, Answer } ]
    }
  };
}, {}));

const responses = [
  { "Id": 1, "Name": "John", "QuestionId": 1, "Answer": 8 },
  { "Id": 1, "Name": "John", "QuestionId": 2, "Answer": 9 },
  { "Id": 1, "Name": "John", "QuestionId": 3, "Answer": 3 },
  { "Id": 1, "Name": "John", "QuestionId": 4, "Answer": 2 },
  { "Id": 2, "Name": "Mark", "QuestionId": 1, "Answer": 6 },
  { "Id": 2, "Name": "Mark", "QuestionId": 2, "Answer": 2 },
  { "Id": 2, "Name": "Mark", "QuestionId": 3, "Answer": 5 },
  { "Id": 2, "Name": "Mark", "QuestionId": 4, "Answer": 1 }
];

const arr = reduceBy(responses, 'Name');

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

Answer №2

const dataArr = [ 
  {Id : 1,Name : "John", QuestionId :1,Answer :8},
  {Id : 1,Name : "John", QuestionId :2,Answer :9},
  {Id : 1,Name : "John", QuestionId :3,Answer :3},
  {Id : 1,Name : "John", QuestionId :4,Answer :2},
  {Id : 2,Name : "Mark", QuestionId :1,Answer :6},
  {Id : 2,Name : "Mark", QuestionId :2,Answer :2},
  {Id : 2,Name : "Mark", QuestionId :3,Answer :5},
  {Id : 2,Name : "Mark", QuestionId :4,Answer :1}
]

let modifiedData = {};
dataArr.forEach(({ Id, Name, QuestionId, Answer }) => {
  if(modifiedData[Id]) {
    modifiedData[Id]["Questions"] = [
      ...modifiedData[Id]["Questions"],
      { QuestionId, Answer }
    ]
  } else {
    modifiedData[Id] = {
      Id,
      Name,
      Questions: [{ QuestionId, Answer }]
    } 
  }
})

console.log(Object.values(modifiedData).flat()); 

Answer №3

let data = [{ID : 1,FirstName : 'Jane', QuestionID :1,Response :8},
           {ID : 2,FirstName : 'Alice', QuestionID :2,Response :9},
           {ID : 3,FirstName : 'Bob', QuestionID :3,Response :3},
           {ID : 4,FirstName : 'Eve', QuestionID :4,Response :2}]

const finalResult = data.reduce((accumulator,currentValue,index,source)=>{
    const {ID, FirstName, QuestionID, Response} = currentValue
    if(index===0 ){
        accumulator.push({ID,FirstName,Question:[{QuestionID, Response}]})
    }else{
        const itemId = accumulator.findIndex(element=>element.ID===currentValue.ID)
        if(itemId>= 0){
            accumulator[itemId].Question.push({QuestionID, Response})
        }else{
            accumulator.push({ID,FirstName,Question:[{QuestionID, Response}]})
        }
    }
  
    return accumulator
},[])

console.log(finalResult)

Answer №4

If you utilize the Set method to identify unique names, you can then use those names to filter items within the Responses array:

let Responses=[{Id:1,Name:"John",QuestionId:1,Answer:8},{Id:1,Name:"John",QuestionId:2,Answer:9},{Id:1,Name:"John",QuestionId:3,Answer:3},{Id:1,Name:"John",QuestionId:4,Answer:2},{Id:2,Name:"Mark",QuestionId:1,Answer:6},{Id:2,Name:"Mark",QuestionId:2,Answer:2},{Id:2,Name:"Mark",QuestionId:3,Answer:5},{Id:2,Name:"Mark",QuestionId:4,Answer:1}];

let result = [...new Set(Responses.map(({Name}) => Name))]
    .map(e => Responses.filter(({Name}) => Name === e))
    
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

Instructions on creating an individual DropdownIndicator component with React-select for the purpose of reusability in different sections of the project

The code below functions properly when the DropdownIndicator component is kept in the same file. However, I am interested in separating DropdownIndicator into its own file so that it can be reused. This way, it can be used as a separate component and incl ...

The component data fails to reflect the updated value following a status change due to not properly retrieving the new result from the POST function

Below is the Vue.js 2 code snippet for sending data to the backend. The vuex library was used to manage the data status. After using the POST function, the result returned from the backend updates the value of sampleId. This value is auto-generated by the ...

Smartlook fails to correctly store user consent

I am currently working on integrating Smartlook into our website. Since we are using React, I am unable to follow the suggested steps in the documentation which can be found here. Our implementation involves initializing Smartlook using a script tag in th ...

Storing the Outcome of a mongodb Search in a Variable

I'm encountering an issue where the result of a MongoDB find operation is not being assigned to a variable (specifically, the line var user = db.collection("Users").findOne below), and instead remains undefined. I am aware that the find function retur ...

typescript: exploring the world of functions, overloads, and generics

One interesting feature of Typescript is function overloading, and it's possible to create a constant function with multiple overloads like this: interface FetchOverload { (action: string, method: 'post' | 'get'): object; (acti ...

Utilizing JSON strings within an onclick function

Hey there, currently I am working on sending an encoded JSON through the onclick attribute. However, I am facing a challenge because the JSON contains strings with a lot of apostrophes and quotes which end up closing the quotes in the onclick attribute. Up ...

Encountering a Module not found error with a ValidationError when trying to import an SVG file within a React

I've set up a manual Webpack 5 configuration for my React project with TypeScript. I am facing an issue while trying to import an SVG icon and using Material UI in the project. The error message I'm encountering is: Module not found: ValidationEr ...

What is the method to extract the value of $r['id_usr'] from a select tag in PHP and store it in a variable?

Is there a way to retrieve the option value from a select tag using $r['usr_id'] when submitting it in order to utilize that value in a php query? Below is an example of my code : <pre> <div class="form-group"> & ...

Move the absolute div by sliding it to the left from 120% to -10px

I want to move an absolute positioned div from the left side of the screen to -10px on button click. Here's my attempt so far, but it's not working as expected. Javascript/jQuery $('.button').click(function() { $(this).parent().f ...

How does assigning a checkbox's value as 'undefined' result in the addition of ng-invalid?

I'm facing an issue with a checkbox in my Angular project. The checkbox has a false value of undefined, and even though it's not marked as required, the form doesn't validate when I check and uncheck it. This is because the class ng-invalid ...

Animations of bezier curves created with Three.js

UPDATED: SOLUTION FOUND I am in need of guidance on how to create animation for the movement of points along a curve to simulate string motion in 3D while keeping performance in mind. Imagine multiple strings between two points, for example. Check out t ...

Having trouble resolving all parameters for the SiteNotificationComponent: (?)

I encountered an issue while attempting to append a component to the DOM. The error message displayed was "Can't resolve all parameters for SiteNotificationComponent: (?).at syntaxError." My goal was to insert HTML content by invoking showNotificatio ...

What to do while waiting for MySQL query in an asynchronous function?

Having an issue with my asynchronous function that queries the database using the mysql library. It seems like the function is not waiting for the query to complete before moving on. Here's the code snippet: async (eventName, eventArgs, app) => { ...

Is there a way to automatically launch a new tab upon arriving from another website?

I currently have a website that displays a table of elements, each with its own set of sub-elements. On another page, I can view the element along with multiple tabs for its corresponding sub-elements. The current setup is depicted as follows: <a clas ...

The chosen selection automatically deactivates the checkbox with a matching value

I am looking for a solution where selecting an option will automatically disable the checkbox with the corresponding value. The existing methods I have come across are static and rely on hardcoded values. <select name="pickOne" id="pickOn ...

How to extract data-bound value from a <span> element using Angular

I have a table that serves as a form, with most of the cells containing input fields. <td><input id="testingInput2" type="number" placeholder="0"step="1" ng-model="addResources.one"> </td> <td><input id="testingInput2" type=" ...

What is the process for assigning a background color to a specific option?

Trying to create a dropdown menu with various options and colors. Managed to set background colors for each option, but once an option is selected, the background color disappears. Is there a way to fix this issue? See my HTML example below: <select> ...

Data will not bind with Laravel and Vue

I am currently working on a Laravel project and trying to develop a basic editing feature for posts. My approach involves using Vue.js 2 to bind the data, but unfortunately, I am facing issues with displaying it - I'm not quite sure what's causin ...

ScriptManager is not accessible in the current ASP.Net Core Razor Page context

I'm facing an issue where I have a view (such as Index.cshtml) and a page model (like Index.cshtml.cs). In the view, there's a JavaScript function that I want to call from the OnPost() method in the page model. I tried using ScriptManager for thi ...

Angular 4: Implementing a Re-login Dialog/Modal Using Interceptors

Issue Description I recently started working with Angular 4 and I am facing a challenge in handling user re-logging when the token expires. Let's Dive Into the Code I have implemented a response intercepter that checks for a 401 error in the respon ...