I am trying to use an array map to filter a object a bit further to prepare it to send to the server to for saving. I can filter to 1 key value, which is great, but I want to take it 1 step further and check them against a boolean inside.
So, right now this is what I have -
$scope.appIds = $scope.applicationsHere.map( function(obj){
if(obj.selected == true){
return obj.id;
}
});
This works great for pulling out the id's, however I don't want to push them in this new array if they their selected value == false, so I put a conditional to filter further. This somewhat works, I get an array of id's, but the id's that have .selected == false are still in the array, just with the value of null. So If I have 4 items in the object and 2 of them are false it looks like this -
appIds = {id1, id2, null, null};
My question is - is there a way to do this without the nulls being put in there. Thanks for reading!
This question is related to
javascript
angularjs
map
You should use Array.prototype.reduce to do this. I did do a little JS perf test to verify that this is more performant than doing a .filter
+ .map
.
$scope.appIds = $scope.applicationsHere.reduce(function(ids, obj){
if(obj.selected === true){
ids.push(obj.id);
}
return ids;
}, []);
Just for the sake of clarity, here's the sample .reduce
I used in the JSPerf test:
var things = [_x000D_
{id: 1, selected: true},_x000D_
{id: 2, selected: true},_x000D_
{id: 3, selected: true},_x000D_
{id: 4, selected: true},_x000D_
{id: 5, selected: false},_x000D_
{id: 6, selected: true},_x000D_
{id: 7, selected: false},_x000D_
{id: 8, selected: true},_x000D_
{id: 9, selected: false},_x000D_
{id: 10, selected: true},_x000D_
];_x000D_
_x000D_
_x000D_
var ids = things.reduce((ids, thing) => {_x000D_
if (thing.selected) {_x000D_
ids.push(thing.id);_x000D_
}_x000D_
return ids;_x000D_
}, []);_x000D_
_x000D_
console.log(ids)
_x000D_
EDIT 1
Note, As of 2/2018 Reduce + Push is fastest in Chrome and Edge, but slower than Filter + Map in Firefox
Here's some info if someone comes upon this in 2019.
I think reduce vs map + filter might be somewhat dependent on what you need to loop through. Not sure on this but reduce does seem to be slower.
One thing is for sure - if you're looking for performance improvements the way you write the code is extremely important!
Here a JS perf test that shows the massive improvements when typing out the code fully rather than checking for "falsey" values (e.g. if (string) {...}
) or returning "falsey" values where a boolean is expected.
Hope this helps someone
You could use flatMap. It can filter and map in one.
$scope.appIds = $scope.applicationsHere.flatMap(obj => obj.selected ? obj.id : [])
Source: Stackoverflow.com