I have two arrays of objects: publications and documentPrices
This is how they look:
const publications = [
{
id: "publication1",
documents: [
{
id: "document1",
priceId: "abc",
},
{
id: "document2",
priceId: "xyz",
},
],
},
{
id: "publication2",
documents: [
{
id: "document3",
priceId: "abc",
},
{
id: "document4",
priceId: "xyz",
},
],
},
]
const documentPrices = [
{ priceId: "abc", priceUsd: 100, priceEur: 120 },
{ priceId: "xyz", priceUsd: 10, priceEur: 12 },
]
I want to achieve the following output
const publicationsFinal = [
{
id: "publication1",
documents: [
{
id: "document 1",
priceId: "abc",
priceUsd: 100,
priceEur: 120,
},
{
id: "document 2",
priceId: "xyz",
priceUsd: 10,
priceEur: 12,
},
],
},
{
id: "publication2",
documents: [
{
id: "document 3",
priceId: "abc",
priceUsd: 100,
priceEur: 120,
},
{
id: "document 4",
priceId: "xyz",
priceUsd: 10,
priceEur: 12,
},
],
},
]
At the moment, I have implemented this with 3 nested loops, which is highly inefficient. Also, I have checked other solutions on SO but haven’t found one that is relevant to the issue I am facing. Is there an efficient way to achieve the desired output?
3
Answers
There always will be 3 loops. It can’t be done without them, but I wouldn’t think about performance if you have less than a million records.
In-place version:
Creating a new object:
It depends on whether you want to modify the objects in the
publications
array or create a new array with new objects. But unless you’re seeing a performance problem, I wouldn’t worry about it too much.Either way, you’re going to have two nested loops (publications and documents), there’s no getting around it. But you can avoid a third nested loop by building a
Map
of the price information up-front:Looking up the entries in the map is required by the JavaScript specification to be faster, in general, than looking up the entries in the array would have been. That is: sublinear.
Once you have the map, if you just want to update the existing objects, you have your nested loops:
(I’ve used
for-of
loops there. These days, JavaScript engines are very nearly as fast atfor-of
as they are atfor
[when using standard arrays], but if you like you could use just afor
loop instead.)Live example:
If you want a new array with new objects, you’d have nested
map
calls (which are loops):Live example:
If you don’t mind creating a new object even if the price information isn’t found, it can be a bit more concise:
Live example:
Turn
documentPrices
into a map:and then merge:
The above mutates, you can also do it by not mutating: