You can also use filter + map like this:
object.cardOptions
.filter(option => option.supported)
.map(cardOption => cardOption.id)
Profiling this side by side using the User Timing API, at least on chrome, it seems like your reduce code is more efficient (but practically it probably won't matter unless you have a really large dataset).
Here's a quick higher order profiling function I often use:
// A function to run an input function several times and profile performance using the User Timing API on chrome
const profile = (func, times) => (...args) => {
const functionName = func.name;
const trackName = `${functionName}`;
const startTag = `${trackName}_start`;
window.performance.mark(startTag);
let results;
for (let i = 0; i < times; i = i + 1)
results = func(...args);
const endTag = `${trackName}_end`;
window.performance.mark(endTag);
window.performance.measure(trackName, startTag, endTag);
return results;
};
const object = {
cardOptions: [
{
id: 'CREDIT',
supported: true,
},
{
id: 'DEBIT',
supported: true,
},
],
};
const filterMap = () => {
object.cardOptions
.filter(option => option.supported)
.map(cardOption => cardOption.id);
};
const reduce = () => {
object.cardOptions.reduce((filtered, cardType) => {
if (cardType.id && cardType.supported) {
filtered.push(cardType.id);
}
return filtered;
}, []);
};
profile(filterMap, 99999)();
profile(reduce, 99999)();
The output of the measure looks like so:
window.performance.getEntriesByType('measure')
[
{
name: 'profileFilterMap',
entryType: 'measure',
startTime: 310637.6400000008,
duration: 30.029999994440004, // higher duration for map + filter
},
{
name: 'profileReduce',
entryType: 'measure',
startTime: 310667.7550000022,
duration: 24.754999991273507, // reduce seems slightly more efficient
},
]
object.cardOptions.reduceinstead ofobject.reducebut that works. I'd personally go forfilter+mapbut it is technically less optimal. Depending on your data, that might not matter, though and if you use something that allows lazy evaluation like Lodash, then you can changeobject.cardOptions.filter().map()with_(object.cardOptions).filter().map()and you'd avoid the double iteration. Ultimately, though Eric Lippert said it best - what is better and if it atters depends on circumstances.