And I want to replace this 2 statements(.map & .filter) with .reduce. How do I do that?
You can't[1] and you shouldn't.
The .reduce function is for when you want to reduce the entire collection to a new single value (or object) such as when you're aggregating values (e.g. SUM, Count, etc) or populating a Set<T>... which is not what you're doing here.
Instead just chain filter and map together in that order: use filter first to eliminate the possibility of encountering undefined or invalid input, then use map to extract the gubbins, then followed by sort for good-measure:
Like so:
this.serverList = data.NodeList
.filter( a => a.productTypeId === '1' && typeof a.HostName === 'string' )
.map( a => a.hostName )
.sort();
Note that .filter and .map are FP-style and so don't modify the input data.NodeList array at all and instead always return new Array objects' whereas the .sort() mutates the array in-place (but still returns it).
Footnote 1:
I wrote "you can't" to discourage people from misusing (IMHO) JS's Array's FP-style functions, which are far easier for a JS engine's JIT to optimize when used as stateless pure functions.
I'll admit that technically reduce can still be used here, but it can only work when using reduce as a substitute for for(of) (or .forEach), but which requires you to avoid invalid input by adding conditional logic (which cannot be optimized as easily by the JIT compared to using map and filter as pure FP functions) which kinda defeats the point of using FP-style functions (again, IMO).
For shits and giggles, I ended up writing a .reduce version, benchmarked here (props to @dancrumb for the challenge) and (to my surprise) my .reduce version ("reduce-only-v2" in that jsPerf benchmark) is actually faster than my filter+map version (at least in Chrome 129 x64 on Windows 10) which suggests that Chrome's JIT does not yet apply parallel-computing optimizations to Array's FP functions - but I'll maintain that the filter+map approach is still preferable to .reduce because it's easier to reason about at-a-glance and also because eventually (I hope!) browsers' JITs will be able to optimize filter+map better for many-core processors than .reduce can:
this.serverList = data.NodeList.reduce( ( acc, a ) => {
if( ( a.productTypeId === '1' ) && ( typeof a.HostName === 'string' ) ) {
acc.push( a.hostName ); // `Array.prototype.push` returns `.length`, so `return acc.push(..);` won't work here.
return acc;
}
return acc;
}, /*seed:*/ [] )
and for fun, let's use everyone's favourite JS operator to reduce har-har it down to a 1-liner:
this.serverList = data.NodeList.reduce( ( acc, val ) => ( a.productTypeId === '1' && typeof a.HostName === 'string' ) ? ( acc.push( a.hostName ), acc ) : acc, /*seed:*/ [] );
...which runs in the same time as the above, but will annoy your coworkers.
undefinedvalues from theserverlistis because you conditionally return a value from the callback function ofmap(). If you need to find a particular item in the array, then you can use thefind()method.reduceis for.reduceis for when you want to reduce the entire list to a single-value, which is not what you're doing. Just chainmapandfiltertogether.Hostnameproperty only whenproductIdis 1. And then I want to sort thehostname. When I map over in the 1st statement, I receivedundefinedas well since those arrays did not haveproductIdvalue as 1. So I filtered out the undefined valuesHostnameproperty of the object withproductId1, then why not just filter the object withproductId1? Why usemap()?aobject with `productTypeId === '1'.