0

The answer in Cartesian product of multiple arrays in JavaScript does not answer my question since my implementation is quite similar to what is said there and I'm only asking about ways to optimize this implementation.

I have two arrays of objects and I want to create one array of objects representing all possible combinations of the first two arrays. To make things clear let's say I have an array of products in supply, an array of products in demand, and I want to see every possible combination of supply and demand. I'm using node.js but the problem is language agnostic.
So if I have:

const supply = [
  {
    id: '1',
    name: 'chair'
  },
  {
    id: '2',
    name: 'desk'
  }
];

const demand = [
  {
    id: '3',
    name: 'couch'
  },
  {
    id: '4',
    name: 'desks'
  }
]

I want the output to be:

[
  {
    id: '1-3',
    supply: 'chair',
    demand: 'couch'
  },
  {
    id: '1-4',
    supply: 'chair',
    demand: 'desks'
  },
  {
    id: '2-3',
    supply: 'desk',
    demand: 'couch'
  },
  {
    id: '2-4',
    supply: 'desk',
    demand: 'desks'
  }
]

To achieve this I implemented the following:

return supply.reduce((acc, supply) => {
  return acc.concat(
    demand.map(demand => {
      return {
        id: `${supply.id}-${demand.id}`,
        supply: supply.name,
        demand: demand.name
      }
    })
  )
}, []);

This works fine, but as my data sets get bigger (right now I have a couple of hundred items in each array, and I'm going to have more soon) it can also get very slow.
Is there any way to optimize this? I can't think of a way to achieve this without iterating over the one array and then over the other for each item of the first array. But maybe I'm missing something?

Please let know if I can provide more information on this.
Any help will be greatly appreciated!

OPearl
  • 349
  • 3
  • 14
  • Don't use `.concat(x)`, which copies all the values into a new array, but use `.push(...x)`. Or even better just replace the entire `reduce`+`concat` with a `flatMap` call. – Bergi Jul 26 '21 at 21:41
  • Not really. It's still nested loops so it doesn't optimize any thing performance wise. – OPearl Jul 27 '21 at 04:25
  • The output array will be as long as the product of the lengths of the input arrays, right? That's a nested loop. – danh Jul 27 '21 at 04:33
  • @danh I guess you're right. As I said I cannot think of an implementation that doesn't involve a nested loop. I just wanted to make sure I'm not missing some creative solution to this problem. – OPearl Jul 27 '21 at 07:13

1 Answers1

-1

The code can be greatly simplified to the following, which should be pretty quick.

demand.forEach((o, i) => {
    acc.push(
    {
        id: `${supply[i].id}-${o.id}`,
        supply: supply[i].name,
        demand: o.name
    })
})
user7296390
  • 160
  • 7
  • This solution does not yield the wanted result. You'll only get a combination of every item in the demand array with its parallel index in the supply array, while the problem is to get all combinations of __every__ supply item with __every__ demand item. – OPearl Jul 27 '21 at 07:16