Using reduce() to group items in an array based on a specific object property

Creating a new array grouped by the property 'desc' of the objects within an existing array is my current task. Here is how I envision it:

const sourceArray = [
  { id: 'id1', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' }
  { id: 'id2', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' }
  { id: 'id3', sourceDesc: 'bar', prop1: 'ignoreme', prop2: 'ignoreme' }
  { id: 'id4', sourceDesc: 'baz', prop1: 'ignoreme', prop2: 'ignoreme' }
];
const targetArray = [
  { desc: 'foo', ids: [
    { id: 'id1', prop1: 'ignoreme', prop2: 'ignoreme' },
    { id: 'id2', prop1: 'ignoreme', prop2: 'ignoreme' }
  ]},
  { desc: 'bar', ids: [
    { id: 'id3', prop1: 'ignoreme', prop2: 'ignoreme' }
  ]},
  { desc: 'baz', ids: [
    { id: 'id4', prop1: 'ignoreme', prop2: 'ignoreme' }
  ]}
];

I believe using the reduce() higher-order function would be the most efficient way to accomplish this. However, I am facing some challenges in adapting the solutions I've found to fit my array structure. Any guidance on how to approach this would be greatly appreciated!

Answer №1

One way to achieve the desired result is by leveraging the power of the .reduce() and .find() methods together:

const inputData = [
  { id: 'id1', dataKey: 'valueA', prop1: 'ignoreme', prop2: 'ignoreme' },
  { id: 'id2', dataKey: 'valueA', prop1: 'ignoreme', prop2: 'ignoreme' },
  { id: 'id3', dataKey: 'valueB', prop1: 'ignoreme', prop2: 'ignoreme' },
  { id: 'id4', dataKey: 'valueC', prop1: 'ignoreme', prop2: 'ignoreme' }
];

const processedData = inputData.reduce((accumulator, currentElement) => {
  const foundElement = accumulator.find(item => item.key === currentElement.dataKey);
  
  if (foundElement) foundElement.ids.push({
    id: currentElement.id,
    prop1: currentElement.prop1,
    prop2: currentElement.prop2
  });
  else accumulator.push({
    key: currentElement.dataKey,
    ids: [{
      id: currentElement.id,
      prop1: currentElement.prop1,
      prop2: currentElement.prop2
    }]
  });
  return accumulator;
}, []);

console.log(processedData);

Answer №2

To achieve the desired result, you can utilize the .reduce() method in combination with Object.entries() and .map() methods:

const data = [
  { id: 'id1', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' },
  { id: 'id2', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' },
  { id: 'id3', sourceDesc: 'bar', prop1: 'ignoreme', prop2: 'ignoreme' },
  { id: 'id4', sourceDesc: 'baz', prop1: 'ignoreme', prop2: 'ignoreme' }
];

const reducer = (arr) => Object.entries(
  arr.reduce((r, { sourceDesc:desc, ...rest }) => {
    r[desc] = r[desc] || [];
    r[desc].push(rest);
    return r;
  }, {})
).map(([k, v]) => ({desc: k, ids: v}));

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

Answer №3

One way to utilize reduce is demonstrated below:

const data = [
  { id: 'id1', 'sourceDesc': 'foo', 'prop1': 'ignoreme', 'prop2': 'ignoreme' },
  { id: 'id2', 'sourceDesc': 'foo', 'prop1': 'ignoreme', 'prop2': 'ignoreme' },
  { id: 'id3', 'sourceDesc': 'bar', 'prop1': 'ignoreme', 'prop2': 'ignoreme' },
  { 'id': 'id4', 'sourceDesc': 'baz', 'prop1': 'ignoreme', 'prop2': 'ignoreme' }
];

const result = data.reduce((output,{id,sourceDesc,prop1,prop2})=>{
  let key = sourceDesc;
  output[key] = output[key] || {des:sourceDesc, ids:[]};
  output[key].ids.push({id,prop1,prop2});
  return output;
},{});

console.log(Object.values(result));

Answer №4

To transform the array into a Map structure, utilize the sourceDesc as the key and then expand the Map.values() iterator to convert it back into an array:

const sourceArray = [
  { id: 'id1', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' },
  { id: 'id2', sourceDesc: 'foo', prop1: 'ignoreme', prop2: 'ignoreme' },
  { id: 'id3', sourceDesc: 'bar', prop1: 'ignoreme', prop2: 'ignoreme' },
  { id: 'id4', sourceDesc: 'baz', prop1: 'ignoreme', prop2: 'ignoreme' }
];

const result = [...
  sourceArray.reduce((r, { sourceDesc: desc, ...o }) => {
    if(!r.has(desc)) r.set(desc, { desc, ids: [] }); 

    r.get(desc).ids.push(o); 

    return r;
  }, new Map)
.values()]; 

console.log(result);

Answer №5

Check out this alternative method for grouping JSON arrays by key using the map function:

const inputArray = [{"id":"id1","sourceDesc":"foo","prop1":"ignoreme","prop2":"ignoreme"},{"id":"id2","sourceDesc":"foo","prop1":"ignoreme","prop2":"ignoreme"},{"id":"id3","sourceDesc":"bar","prop1":"ignoreme","prop2":"ignoreme"},{"id":"id4","sourceDesc":"baz","prop1":"ignoreme","prop2":"ignoreme"}];

const targetKey = 'sourceDesc';

const groupedArray = [...new Map(inputArray.map(item =>
  [item[targetKey], inputArray.filter(x=>x[targetKey] == item[targetKey])]))
 /*uncomment to flatten array*/ //.values()
];

console.log(groupedArray);

   /*EXPECTED OUTPUT
       [
  [
    "foo",
    [
      {
        "id": "id1",
        "sourceDesc": "foo",
        "prop1": "ignoreme",
        "prop2": "ignoreme"
      },
      {
        "id": "id2",
        "sourceDesc": "foo",
        "prop1": "ignoreme",
        "prop2": "ignoreme"
      }
    ]
  ]
]
   */

Answer №6

To achieve this, we can utilize the forEach method and create an object with keys corresponding to the values of sourceDesc.

const sourceArray = [
  { id: "id1", sourceDesc: "foo", prop1: "ignoreme", prop2: "ignoreme" },
  { id: "id2", sourceDesc: "foo", prop1: "ignoreme", prop2: "ignoreme" },
  { id: "id3", sourceDesc: "bar", prop1: "ignoreme", prop2: "ignoreme" },
  { id: "id4", sourceDesc: "baz", prop1: "ignoreme", prop2: "ignoreme" }
];

const update = data => {
  const res = {};
  data.forEach(({ sourceDesc, ...item }) => {
    if (!res[sourceDesc]) {
      res[sourceDesc] = { desc: sourceDesc, ids: [] };
    }
    res[sourceDesc].ids.push(item);
  });
  return Object.values(res);
};

console.log(update(sourceArray));

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 have developed a website that can calculate the factorial of any given number. The next step is to design a function that will display the step-by-step mathematical process

Could use a hand with this one. The function below is empty and I'm a bit stuck on what to do next. Right now, the webpage displays the factorized number, but I want to show the mathematical equation before it, like so: User inputs: 3 Site outputs: " ...

Steps to display the leave site prompt during the beforeunload event once a function has finished running

While facing a challenge with executing synchronous Ajax methods in page dismissal events, I discovered that modern browsers no longer support this functionality in the "beforeunload" event. To work around this issue, I implemented a new promise that resol ...

Generating elevation graph from a kml file with the combination of php and javascript

Currently, I am exploring the Google Elevation Service with the goal of creating an elevation profile similar to the one showcased in this example: Below is the JavaScript code snippet used: var elevator; var map; var chart; var infowindow = new google.m ...

Activate filtering beyond the AngularJS datatable

Currently, I am experimenting with a codepen to understand how to filter data based on a clicked span element. The table is where the data is displayed and I'm looking for a way to trigger filtering outside of it. While the angularjs documentation spe ...

Dynamic jquery panel that remains expanded while concealing the menu on large screens

The page demonstrating jquery features automatically opens a side panel on large screens and displays a logo image instead of the standard 'open panel' icon. It remains open until the screen size is reduced. Take a look at the demonstration here: ...

What is the process of integrating an HTML web component with an HTML file? Can I use innerHTML = foo("myfile.html") to achieve

Using HTML web components allows me to define their code using this method: this.innerHTML = `<h1></h1>`; However, I find it cumbersome as I do not have access to the Emmet Abbreviation feature which slows down my component creation process. ...

When utilizing exit-hook with process.on('SIGTERM'), child_process spawn requires two control-c commands to exit properly

I have the following program running: const { spawn } = require("child_process"); const exitHook = require("exit-hook"); exitHook(() => { console.log("Leaving"); }); spawn("my-program", ["my-args"], { stdio: "inherit" }); // Long running server ...

Is there a way to organize a list of arrays within a loop based on a specific index within each array in JavaScript?

Greetings, I am currently facing an issue with sorting a specific object of arrays. The structure is as follows: Allow me to provide a clearer example - I am receiving a string from an AJAX call formatted like this: "name|price|blah|blah@name|price|blah| ...

Gain access to JSON information and store it in the datasource variable using the Kendo datasource function

Within my asp.net project, I have utilized the following approach to extract Json data from a js file: var ds = new kendo.data.DataSource({ transport: { read: { url: "http://localhost:2544/JS/emp ...

Incorporating a dynamic fill effect into an SVG pie chart

I am looking to animate a pie chart with a variable value that is unknown upon loading. Assuming I fetch the value promptly and convert it into a rounded percentage : var percentage = Math.round(sum * 100 / total); Next, I place this value here : <di ...

Invoke the javascript function by referencing the JavaScript file

I'm encountering an issue with two JavaScript files. One file uses the prototype syntax, while the other utilizes jQuery. Unfortunately, they don't seem to work harmoniously together. I've attempted calling the functions within the files usi ...

Tips on finding the ID of a textbox using the cursor's position

In the container, there are several textboxes. When a button is clicked, I want to insert some text at the cursor position in one of the textboxes. I have managed to insert text into a specific textbox using its ID, but I am facing difficulty in identifyin ...

Implementing Text Box Control Validation within a Gridview using UpdatePanel in c# ASP.Net

In my gridview, one of the columns contains a Text Box Control. I am looking to validate the text entered by users as alphanumeric characters and spaces only. Allowed characters are: a-z, A-Z, 0-9, and space. I want to perform this validation using Java ...

Upon reloading, the dynamically generated table does not appear accurately

When a table is dynamically created using JavaScript/jQuery/html from an Ajax call, it initially displays correctly formatted. However, upon refresh/reload, the formatting of the table becomes incorrect. To address this issue, I have implemented a Promise ...

The file 'index.js' does not have a default export

Stepping into the world of MERN development, I embarked on a journey to construct a learning management system based on an outdated tutorial. To my dismay, I encountered the following error: > ..\server\middlewares\index.js:1 > import ...

Expanding the jQuery AutoComplete Plugin: A Guide to Implementing the bind keyup Event

Currently, I am utilizing a plugin that enhances the features of the jQuery AutoComplete UI Plugin: https://github.com/experteer/autocompleteTrigger/blob/master/jquery-ui.autocompleteTrigger.js Within the select method, an event and ui variable are passe ...

Using Vue.js to Delete an Element from an Array

I am facing an issue with my form value where the IDs are not getting deleted when I remove data. Each time I save data, a new ID is added to the list in the form value. But when I delete any of those data entries, the corresponding ID is not removed from ...

Strange actions observed in JavaScript addition operations

In my Angular application, I have the following TypeScript function: countTotal() { this.total = this.num1 + this.num2 } The value of num1 is 110.84 and the value of num2 is 5.54. I determined these values by watching this.num1 and this.num2 in the C ...

Adapt vanilla JavaScript code to be compatible with Node.js, MongoDB, and Express framework

In the midst of working on a blog project for my class, I find myself faced with the challenge of integrating Nodejs, Mongo, and Express into our existing setup. Up until now, we have been gradually transitioning to using Express in our application develop ...

Utilizing angular.forEach in $scope to extract data from an array

I am working with a dynamically changing array based on another piece of code and I am attempting to extract specific data from it. Here is an example of one dynamically generated array stored in $scope.filtereditem: [{ "active": true, "createdAt": " ...