I am working on something where I take data from 2 different APIs that I have no control of and I want to combine the results in the most efficient way. One of the arrays hold some assets, lets say books, the other one holds a transaction for the said book. Here is an example:
{
author: {name: 'J.K. Rowling', },
assetName: 'Book1'
}]
const array2 = [
{from: 'John',
to: 'Sarah,
price: 10,
timeStamp: 123,
assetName: 'Book1',
authorName: 'J.K. Rowling'
}]
Note that to find the corresponding transaction for a given book, you need both assetName and authorName to match - you can own more than one book of the same author and you can own two books with the same name but a different author but an author has only one book with a given name, thus finding the corresponding transaction to an asset requires both fields to match and there are no other unique identifiers. The naive approach is to iterate over one of the arrays and for each entry to check in the second array to find the transaction but that looks like it will take too long to execute if the arrays are of substantial size. I was wondering what better solutions can you think of for merging two objects with different structure that is efficient?
CodePudding user response:
Well, if author.name
assetName
form an id, you could iterate over array1
once & create a Map
with keys being author.name assetName
& vales being original objects.
Then you could iterate over array2
once as well & enrich it whatever way you want. All lookups in the second iteration will be fast since you will access the Map
instead of searching in array.
const indexedArray1 = new Map();
array1.forEach(data => indexedArray1.set(data.author.name data.assetName, data);
const enrichedArray2 = array2.map(transaction => {
const relatedBook = indexedArray1.get(transaction.authorName transaction.assetName);
// Merge relatedBook & transaction the way you want here
});
CodePudding user response:
I often do the following when merging arrays
The time complexity is O(n)
const array1 = [{
author: {name: 'J.K. Rowling' },
assetName: 'Book1'
}]
const array2 = [{
from: 'John',
to: 'Sarah',
price: 10,
timeStamp: 123,
assetName: 'Book1',
authorName: 'J.K. Rowling'
}]
const array2_map = {}
array2.forEach(e => {
const key = `${e.assetName}:${e.authorName}`
if (!array2_map[key]) array2_map[key] = []
const { from, to, price, timeStamp } = e
array2_map[key].push({
from,
to,
price,
timeStamp
})
})
const merged_array = array1.map(e => ({
...e,
transaction: array2_map[`${e.assetName}:${e.authorName}`] || []
}))