Changing an array of objects into an array of arrays while maintaining the original order in JavaScript

My task involves taking an array of objects and converting it into nested arrays based on the position property, while still preserving the original order.

Here is my approach:

const data = [{
  position: 'left',
  message: 'a'
}, {
  position: 'left',
  message: 'b'
}, {
  position: 'left',
  message: 'c'
}, {
  position: 'right',
  message: 'd'
}, {
  position: 'right',
  message: 'e'
}, {
  position: 'left',
  message: 'f'
}, {
  position: 'left',
  message: 'g'
}]

console.log(data.reduce((a, c) => {
  let b = [];
  let d = [];
  if (c.position === 'left') {
    b.push(c.message)
  }
  if (c.position === 'right') {
    d.push(c.message)
  }
  a.push(b)
  return a
}, []))

Desired output:

[['a', 'b', 'c'], ['d', 'e'], ['f', 'g']]

The elements with the same position are grouped together in their own array. If the position changes, a new array is created for the next set of elements. For example, 'a' 'b' 'c' have left position and form one array, 'd' 'e' have right position and are in another array, and 'f' 'g' also have left position forming a separate array.

Thank you.

Answer №1

Instead of hard-coding the creation of two arrays in the .reduce callback, consider using the iteration index to determine the last index position and create new arrays accordingly. It might be better to avoid using .reduce here as it can make the code harder to understand.

const data = [{
  position: 'left',
  message: 'a'
}, {
  position: 'left',
  message: 'b'
}, {
  position: 'left',
  message: 'c'
}, {
  position: 'right',
  message: 'd'
}, {
  position: 'right',
  message: 'e'
}, {
  position: 'left',
  message: 'f'
}, {
  position: 'left',
  message: 'g'
}]

console.log(data.reduce((a, { position, message }, i, arr) => {
  const lastPosition = arr[i - 1]?.position;
  if (lastPosition !== position) a.push([]);
  a[a.length - 1].push(message);
  return a
}, []))

If you prefer a more readable approach without using .reduce:

const data = [{
  position: 'left',
  message: 'a'
}, {
  position: 'left',
  message: 'b'
}, {
  position: 'left',
  message: 'c'
}, {
  position: 'right',
  message: 'd'
}, {
  position: 'right',
  message: 'e'
}, {
  position: 'left',
  message: 'f'
}, {
  position: 'left',
  message: 'g'
}];

let lastPosition;
const result = [];
for (const { position, message } of data) {
  if (position !== lastPosition) result.push([]);
  result[result.length - 1].push(message);
  lastPosition = position;
}
console.log(result);

Answer №2

To group items, consider referencing the previous object in the array.

const
    data = [{ position: 'left', message: 'a' }, { position: 'left', message: 'b' }, { position: 'left', message: 'c' }, { position: 'right', message: 'd' }, { position: 'right', message: 'e' }, { position: 'left', message: 'f' }, { position: 'left', message: 'g' }],
    result = data.reduce((r, o, i, a) => {
        if (o.position !== a[i - 1]?.position) r.push([]);
        r[r.length - 1].push(o);
        return r;
    }, []);

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

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

Is there a similar concept to "Symbol.iterator" for the object spread syntax { ...obj } in JavaScript?

One symbol that is widely recognized is Symbol.iterator. When this symbol is defined as a generator function property on an object, it enables the object to be utilized in a [...object] syntax. For example, you can do something like this: const newArray = ...

What is the best way to transmit data to a PHP script using AJAX?

I'm facing an issue with my basic ajax script not running. The code I have should work fine. The ajax script is: <html> <head><title>Testing ajax</title> <script type="text/javascript"> function ajax() { ...

Is forked processes included in node.js --max-old-space-size?

Currently, I am tackling out-of-memory errors in a node.js application by utilizing the --max-old-space-size parameter when launching node. I have set the size to 4096MB, which is the maximum as per https://github.com/nodejs/node-v0.x-archive/wiki/FAQ (I c ...

Having trouble accessing JSON response properties within an Angular.js controller

My Angular.js controller is called 'forecastController'. This is the code for the Angular.js Controller: weatherApp.controller('forecastController', ['$scope','$routeParams','cityService', 'weat ...

What could be causing this error in the jQuery AJAX post request, even though the post was actually successful?

I created a blogging platform using Laravel 8. Currently, I am focused on implementing comment submissions and replies using jQuery (v3.5.0) AJAX. This is the function for adding a comment: public function add_comment( Request $request ) { $rules = [ ...

Unable to specify the element within the array

I'm having trouble getting my array elements defined. When I try to alert them, I always receive NaN. Even though the jQuery selectors seem to be working perfectly. Can someone help me figure out what the problem might be? var sldr ...

`Can you please explain how to retrieve the current state in React?`

PROGRAMMING ISSUE: initializeState: function() { return { title: "", description: "" } }, submitForm: function() { var newTask = { title: this.state.title, description: this.state. ...

Using router.get with a redirect in Express

Can you directly invoke a router.get(...) function in Express? Let's say I have a router.get('/my-route', function(req, res) { ... });, is it feasible to then, within another part of my code, use res.redirect('my-route'); with the ...

Ways to enable Ajax functionality in a FancyBox created by Ajax

I've encountered an issue while using the FancyBox plugin. I'm attempting to submit a form with Ajax and simply display a nice success message without validation, just trying to make it work. I can successfully submit with jQuery and show the inp ...

Creating a column chart with dynamic data in Angular using Highcharts

I have successfully integrated high charts in angular js using hard coded data. However, I am facing an issue when trying to display dynamic data fetched from a web service. In my controller: $scope.months = []; $scope.retail = []; $scope.wholesale = []; ...

Tips for maintaining consistency between server-side Java and client-side JS DTO properties

Greetings, I am in search of a solution or plugin within Eclipse that can ensure synchronization between server-side Java DTO properties and their corresponding client-side JSON elements as the codebase evolves. For instance, in a web application with a Ja ...

Utilizing the power of jQuery within three.js

Thank you once again for your previous assistance, but I find myself in need of your expertise once more. I have successfully added markers to my map as desired. However, these markers now require functionality to be clickable. Specifically, when clicked, ...

Is it possible to remove Google Markers?

I am facing an issue with rendering Markers on the map in my React component. Whenever I update the markers array, the new markers appear but the old ones remain on the map. For example, if I change the coordinates in the parent component, both the old and ...

What is the difference between using 'classes' and 'className' in Material UI?

I find myself a bit perplexed about these two properties. Let's say I have, const useStyles = makeStyles(() => ({ style: { width: 600, height: 400, }, })); With this, I can use, const classes = useStyles(); <SomeComponent classNa ...

The marvels of HTML5 Canvas clipboard

Currently working on integrating a clipboard feature for our html5 text editor. Our canvas setup is causing challenges when it comes to achieving seamless copy and paste across all browsers. We've explored zeroclipboard, but have found it to be lackin ...

How can you display the <script> tag in GatsbyJs?

I am facing an issue with my strapi and gatsby project. The Strapi editor uses markdown, so I receive a string with markdown content. Some of the blog posts created on Strapi contain charts that have script and div elements. When using markdown to jsx, t ...

Encountering an issue when trying to upload a file for the second time

I am currently working on a project where I need to upload an excel file and send it to an API using ReactJS. So far, I have been able to successfully send the file to the API. However, in my submit function, I want to reset the saved excel file from the s ...

Middleware in Express can be executed more than once

I am encountering a frustrating issue where my middlewares are being called multiple times without explanation. Despite having written short and simple code while learning Express and Node, I cannot pinpoint the reason for this behavior. I find it confusin ...

Creating a Python server for an Angularjs application and capturing user input

Can you offer me some assistance, whether it's just a hint or a useful tip that could improve my current approach? I have created a series of forms using HTML and AngularJS. Each form collects input data from users, which is then stored in a JSON str ...

Reactjs button only responds on the second click instead of the first tap

Currently, I am working on a Reactjs/nextjs project and have a video with audio button on my page. There are two things that I want to achieve: 1) I would like the button to have the "bi bi-volume-mute" class by default instead of "bi bi-volume-down". 2) W ...