How do you map a JavaScript array to another just like the RDB?
There are some approaches to realize it, but we should go with performant one as much as possible.
Let's say you have these arrays.
const arr1 = [
{ id: 'id001', value: 'value1' },
{ id: 'id002', value: 'value2' },
{ id: 'id003', value: 'value3' },
{ id: 'id004', value: 'value4' },
];
const arr2 = [
{ value: 'id001', label: 'label1' },
{ value: 'id002', label: 'label2' },
{ value: 'id003', label: 'label3' },
];
Then, we want this output.
const output = [
{ id: 'id001', value: 'value1', label: 'label1' },
{ id: 'id002', value: 'value2', label: 'label2' },
{ id: 'id003', value: 'value3', label: 'label3' },
{ id: 'id004', value: 'value4', label: '-' },
];
Approach 1 (iteration)
This works, but not performant because Array.filter()
iterates items in arr2 one by one.
const output = arr1.map(item1 => {
const _matched = arr2.filter(item2 => item2.value === item1.id);
const label = _matched.length ? _matched[0].label : '-';
return {
...item1,
label,
};
});
Approach 2 (converting one to object)
It is better to convert one array to object which can be refferred by another array.
It can prevent one-by-one iteration matching.
However, if arr2 has many items, it is still heavy loaded.
const _convetedObj = arr2.reduce((acc, item) => {
return {
...acc,
[item.value]: item.label,
};
}, {});
const output = arr1.map(item => {
return {
...item,
label: _convertedObj?[item.id] ?? '-',
}
});
Approach 3 (Array.find())
This is the simplest approach I like the most!
Use Array.find(). (This is more performant, since the predicate function will be executed fewer times than like filter(), if the target item is found early)
const output = arr1.map(item => {
return {
...item,
label: arr2.find(({ value }) => value === item.id)?.label ?? '-',
};
});