Sort items into two arrays based on a common value

I'm struggling to group items from one array based on a value from another array, but I can't seem to figure out the right approach.

In my orders array, each object has a key-value pair like id: 999324. Now, in another array for products, there are multiple objects with different or matching ids like orderlineId: 999324. My goal is to group together those objects with matching IDs.

Order array

[{
    "agreement": null,
    "channel": null,
    "collection": "Colect 2019",
    "comment": "Comment here",
    "customerNo": "140159",
    "customerOrderReference": "CustomerOReference",
    "customerPriceGroup": "1,7",
    "erpOrderReference": "1337ORDERREFERENCE",
    "externalUrl": null,
    "id": 99945333,
},
{
    ...
]

Products array

[{
        "crossReference": null,
        "currency": "EU",
        "deliverySubBlock": null,
        "eanCode": "8717945155406",
        "grossLineAmount": 99.99,
        "grossWholesalePrice": 99.99,
        "id": 1156718740,
        "orderlineId": 99945334,
},
{
    ...
}]

The desired output would be an array of orders with nested arrays containing all products that match the orders.id and products.orderlineId.

[{
{
    "agreement": null,
    "channel": null,
    "collection": "Colect 2019",
    ...
    "id": 99945334,
    "orderLines" [
     {
        ...
     },
     ...
},
{
    ...
}]

I've attempted various methods, such as:


for(let i=0; i<orders.length; i++) {
  merged.push({
   ...products[i], 
   ...(orders.find((itmInner) => itmInner.id === products[i].orderlineId))}
  );
}

But it's not yielding the correct result. Any guidance on what I may be doing wrong would be greatly appreciated.

I hope I've explained my issue clearly since this is my first post on Stack Overflow.

Answer №1

This code snippet utilizes the filter method to filter for matching ids and mutates the objects in the orders array.
To optimize performance for large data sets, it is recommended to use an object map lookup table to track ids. This way, you can avoid iterating through the entire products array for every order, reducing complexity from O(N^2) to O(N).
(You would create an object map based on orders' ids, allowing you to iterate through the orders array only once and then through the products array only once)

orders.forEach(order=>
  order.productLines = products.filter(p => p.orderlineId === order.id)
)

console.log(orders)
<script>
orders = [{
    "agreement": null,
    "channel": null,
    "collection": "Colect 2019",
    "comment": "Comment here",
    "customerNo": "140159",
    "customerOrderReference": "CustomerOReference",
    "customerPriceGroup": "1,7",
    "erpOrderReference": "1337ORDERREFERENCE",
    "externalUrl": null,
    "id": 99945333,
},
{
    "agreement": null,
    "channel": null,
    "collection": "Colect 2019",
    "comment": "Comment here",
    "customerNo": "140159",
    "customerOrderReference": "CustomerOReference",
    "customerPriceGroup": "1,7",
    "erpOrderReference": "1337ORDERREFERENCE",
    "externalUrl": null,
    "id": 99945334,
}]

products = [{
        "crossReference": null,
        "currency": "EU",
        "deliverySubBlock": null,
        "eanCode": "8717945155406",
        "grossLineAmount": 99.99,
        "grossWholesalePrice": 99.99,
        "id": 1156718740,
        "orderlineId": 99945334,
},
{
        "crossReference": null,
        "currency": "EU",
        "deliverySubBlock": null,
        "eanCode": "8717945155406",
        "grossLineAmount": 99.99,
        "grossWholesalePrice": 99.99,
        "id": 1156718740,
        "orderlineId": 99945334,
},
{
        "crossReference": null,
        "currency": "EU",
        "deliverySubBlock": null,
        "eanCode": "8717945155406",
        "grossLineAmount": 99.99,
        "grossWholesalePrice": 99.99,
        "id": 1156718740,
        "orderlineId": 99945334
}]
</script>

Answer №2

To achieve what you're looking for, start by including the order in the merged array as the order will always be one of the products, and then add the orderlineId of the product that matches the id of the order.

Since the orders array contains all the orders and the products array may have more elements than orders, the loop should iterate through the length of the products array. This way, the merged array will group all elements with the same value together.

Does this align with your objective?

products.forEach(product => {
    let order = orders.find(order => product.orderlineId === order.id)
    merged = [...merged, { ...product, ...order } ]
})

Let's consider an example with orders array:

let orders = [{ id: 23432}, {id: 11111}, {id: 56789}];
let products = [{orderlineId: 83}, {orderlineId: 11111}, {orderlineId: 56789}, {orderlineId: 23432}]
let merged = []

// after running the above code snippet, the merged array would look like this...

merged = [
{orderlineId: 83}, 
{orderlineId: 11111, id: 11111},
{orderlineId: 56789, id: 56789},
{orderlineId: 23432, id: 23432}
]

Does this result match your expectations? If so, interchange products with orders and orders with the products array in your loop.

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

How to interact with a C# List using JavaScript

Our internship project entails creating a business application using Unity WebGL. However, we're facing a challenge when it comes to retrieving a list from C# to populate a Select element on our webpage. We've successfully communicated and retrie ...

Attempting to switch between classes with the click of a button

I am attempting to create a basic animation that involves changing an image from A to B to C when a button is clicked. However, I am encountering an issue with the error message Cannot read properties of undefined (reading 'classList'). I am puzz ...

Create PDF files on-the-fly using the html-pdf module

Recently, I've been using the npm package html-pdf for generating PDF invoices dynamically. However, I encountered a problem where instead of saving values to the PDF file, it was saving ejs code. Does anyone have any insight on why this might be happ ...

The issue I am facing is that the Vuetify v-data-table is failing to display the data

I'm relatively new to working with javascript and vue/vuetify. Currently, I have a v-data-table that I can fill with static data. However, I'm looking to populate it upon clicking through a Flask API call. This is what I have so far: index.htm ...

Visual Matrix and Directional Controls

I'm currently learning JavaScript and I've put together this script from different sources to help me grasp the basics. I prefer to keep it simple and would appreciate explanations if it gets too complex. Don't assume I know too much about i ...

How come I lose a day when attempting to convert a date to an ISO string in JavaScript?

I've been attempting to convert a date object to the ISOString() format, but it's consistently returning a result that is 1 day off (i.e., it subtracts 1 day). var fromDate = { day:4, month:5, year:2012 } var fromDateString = new Date ...

Issue with displaying nested React Elements from Component

I am currently facing an issue with my Collection component, which is utilizing a sub-component called RenderCollectionPieces to display UI elements. Strangely, I am able to see the data for image.name in the console but for some reason, the UI elements ar ...

Icons positioned absolutely outside of components will not be responsive to user interactions

How can I ensure that the icon on my tab bar can be clicked only when it covers a specific part of the screen, and not when it is in other areas? Any suggestions on how to fix this? Image Below is the code for the tab bar: <View style={{ background ...

Developing a unique bundle with tailored elements

I am interested in developing a custom Material UI component and making it available as a standalone package within my company's private NPM repository. Specifically, I have customized the Date Picker to create a Date Range Picker since Material UI d ...

Why is the code able to execute following the setState hook without any listener declared in the useEffect hook?

Recently, I came across an expo barcode scanner example where a function is executed after a setState hook. This puzzled me as I thought that calling the setState hook would trigger a re-render of the component. Can anyone explain why the function runs aft ...

Passing default props to a component in React that includes a function as one of the

I am working on a React component that has default props set. The issue arises when I try to pass an additional prop, specifically a function. class MyComponent extends Component { constructor(props) { console.log('props', props); supe ...

Is it possible to showcase a dropdown list within a constantly changing table?

I have a table code snippet that I need help with <fieldset class="tabular"><legend><%= l(:redmine_taskjuggler) %></legend> <%= labelled_fields_for(@issue) do |f| %> <div id="taskjuggler" class="attributes"> <div cl ...

Tips for utilizing state and city dropdown menus in JavaScript multiple times without interfering with other dropdowns

Currently, I am utilizing CodeIgniter to create a dynamic dropdown functionality. The setup involves four select country dropdowns where the state options will populate based on the selected country, and once a state is chosen, the corresponding city optio ...

"GM_openInTab in Userscript (Scriptish) not working properly, returning null value

There seems to be a problem with window.opener that I am facing. When I utilize window.open("url"), the child window will reference window.opener properly. However, if I use GM_openInTab instead, which is supposed to be the equivalent option for cross bro ...

Preventing Express.JS HTTP requests from being blocked by npm cron

I'm experimenting with the cron module from npm within my Express.js application. The structure of my app is quite straightforward. I have a function to establish a connection to the database, where I then register all the different modules that hand ...

Is there a problem with the alignment of

<s:form id="inputThresholdForm" name="inputThresholdForm" theme="simple"> <table border="0" class="display-table" cellspacing="2" cellpadding="2" height="100%" width="100%"> <tr> <td colspan= ...

How can I move a TableItem from one material UI component to another using drag-and-drop?

I am facing an issue where I need to drag a ListItem from one List component to another. I am uncertain about how to accomplish this in Material UI. ...

Get ready for 10 AM with the RxJS timer function

I am trying to figure out how to schedule a method in my code using rxjs/timer. Specifically, I want the method to run at precisely 10 AM after an initial delay of 1 minute. However, my current implementation is running every 2 minutes after a 1-minute d ...

Is it possible to hide a fixed header on scroll in a mobile device?

I am facing an issue with my Wordpress site where I want the header to hide when the user scrolls. Despite trying various codes, I have been unable to make it work. The reason for wanting to hide the header is that on mobile devices, it causes scroll prob ...

Retrieve and dynamically load an entire webpage using AJAX

Although it's typically not recommended, I am interested in displaying the progress of a download on a heavy page to show the user when it's ready. Is there a way for me to track and display the actual progress of the download? Can I monitor how ...