Reputation: 13636
I have this array and variable:
var freqId = 45;
$scope.frequencies = [{Id:124,name:'qqq'},
{Id:589,name:'www'},
{Id:45,name:'eee'},
{Id:567,name:'rrr'}]
I use this row to get all id's from array above:
var inspectionsId = $scope.frequencies.map(function (obj) { return obj.Id; })
The result I get is:
var Id's = [124,589,45,567];
I need to change this row:
$scope.frequencies.map(function (obj) { return obj.Id; })
to retrive all id from frequencies array except where Id equal to freqId variable.
For example desired result is:
var inspectionsId = [124,589,567];
Any idea how can I implemet it?
Upvotes: 1
Views: 2100
Reputation: 1075885
You'll have seen the filter
answers. 99.999% of the time, that's the way to go.
If you have a truly massive array and you think it's important to make just a single pass through it, you could give yourself a function combining map
and filter
:
// A value to use to mean "leave entry out"
Object.defineProperty(Array.prototype, "OMIT", {
value: {}
});
// The utility function
Object.defineProperty(Array.prototype, "mapFilter", {
value: function(f, thisArg, omissionFlag) {
var result = [];
if (arguments.length < 3) {
omissionFlag = Array.OMIT;
}
Object.keys(this).forEach(function(index) {
var value = f.call(thisArg, this[index], index, this);
if (value !== omissionFlag) {
result.push(value);
}
}, this);
return result;
}
});
// Using it
var freqId = 45;
var input = [{Id: 124, name: 'qqq'}, {Id: 589, name: 'www'}, {Id: 45, name: 'eee'}, {Id: 567, name: 'rrr'}];
var output = input.mapFilter(function(obj) {
return obj.Id == freqId ? Array.OMIT : obj.Id;
});
console.log(output);
This version accepts up to three arguments:
The map/filter function
The value to use as this
during callbacks
The value to use to mean "omit this entry," which defaults to Array.OMIT
It calls its callback with the value, index, and array just like forEach
and map
and such do.
Again, though, I'll emphasize that in the vast, vast majority of cases, filter
and then map
(or map
and then filter
if the map
makes filter
ing easier) is the way to go.
That said, a generic "loop with memo" function has broader applicability:
// The utility function
Object.defineProperty(Array.prototype, "memoLoop", {
value: function(memo, f, thisArg) {
Object.keys(this).forEach(function(index) {
f.call(thisArg, memo, this[index], index, this);
}, this);
return memo;
}
});
// Using it
var freqId = 45;
var input = [{Id: 124, name: 'qqq'}, {Id: 589, name: 'www'}, {Id: 45, name: 'eee'}, {Id: 567, name: 'rrr'}];
var output = input.memoLoop([], function(result, obj) {
var id = obj.Id;
if (id != freqId) {
result.push(id);
}
});
console.log(output);
It's a bit like Array#reduce
but assumes an unchanging memo value (in our case, the new array), which simplifies the callback somewhat.
Upvotes: 1
Reputation: 64943
You can also use Array.prototype.reduce
to do both filtering and mapping in a single loop:
var freqId = 45;
$scope = {}; // Dummy scope
$scope.frequencies = [{
Id: 124,
name: 'qqq'
}, {
Id: 589,
name: 'www'
}, {
Id: 45,
name: 'eee'
}, {
Id: 567,
name: 'rrr'
}]
var result = $scope.frequencies.reduce(function(result, current) {
if (current.Id != freqId) {
result.push(current.Id);
}
return result;
}, []);
console.log(JSON.stringify(result));
Upvotes: 4
Reputation: 179
You can use Array.prototype.filter
:
var inspectionsId = $scope.frequencies
.map(function(obj) { return obj.Id; })
.filter(function(id) { return id !== 45 })
Upvotes: 2
Reputation: 944556
map
is designed to transform data, not filter it. Chain it with filter
for the latter.
var freqId = 45;
var input = [{
Id: 124,
name: 'qqq'
}, {
Id: 589,
name: 'www'
}, {
Id: 45,
name: 'eee'
}, {
Id: 567,
name: 'rrr'
}];
var output = input.map(function(obj) {
return obj.Id;
}).filter(function(element) {
return element != freqId
});
console.log(output);
Upvotes: 2