Reputation: 5764
I'm wondering, if there is a way to filter an array or stream and apply a function A to all matches and a function B to all non-matches in JavaScript. Here is some example code that explains it a bit more:
// initial data
var names = ['Matthias', 'Maria', 'Bob', 'Anton'];
var namesWithM;
var namesWithoutM;
// gets only names starting with M, but not the others at the same time
namesWithM = names.filter(name => name.startsWith('M'))
// conditional lambda version
namesWithM = [];
namesWithoutM = [];
names.forEach(name => name.startsWith('M') ? namesWithM.push(name) : namesWithoutM.push(name));
// conditional classical version
namesWithM = [];
namesWithoutM = [];
names.forEach(function(name) {
if (name.startsWith('M'))
namesWithM.push(name)
else
namesWithoutM.push(name);
});
The very first version handles just the matches but uses filter
and not forEach
. Is there any way to use filter
and apply a function for matches and non-matches at once? Something like this pseudo code:
names.filter(name.startsWith('M')).apply(namesWithM::push).or(namesWithoutM::push);
Upvotes: 1
Views: 40
Reputation: 11283
I would use reduce
to group data into 2 mentioned cases. I don't see any reason to use filter
here
let names = ['Matthias', 'Maria', 'Bob', 'Anton'];
let [namesWithM, namesWithoutM] = names.reduce((acc, name) => {
if (name.startsWith('M')) {
acc[0] = [...(acc[0] || []), name]
return acc;
}
acc[1] = [...(acc[1] || []), name]
return acc;
}, [])
// simpler version
console.log(namesWithM, namesWithoutM);
let [namesWithM1, namesWithoutM1] = names.reduce((acc, name) => {
const index = Number(!name.startsWith('M'));
acc[index] = [...(acc[index] || []), name];
return acc;
}, [])
console.log(namesWithM1, namesWithoutM1);
Upvotes: 1
Reputation: 50291
filter returns an array. So you can use this array to fill with name
which either starts with M
or not.
In the below example the filter is filling the array with name starts with M
. In filter
callback the name not starting with M are filled in another array
// initial data
var names = ['Matthias', 'Maria', 'Bob', 'Anton'];
var namesWithM;
var namesWithoutM = [];
namesWithM = names.filter((name) => {
if (!name.startsWith('M')) {
namesWithoutM.push(name)
}
return name.startsWith('M');
});
console.log(namesWithM, namesWithoutM);
Upvotes: 2
Reputation: 1
const names = ['Matthias', 'Maria', 'Bob', 'Anton'];
function A(item){
console.log('filtered');
console.log(item);
}
function B(item){
console.log('not-ffiltered');
console.log(item);
}
const filteredNames = names.filter(name => {
const isValid = name.startsWith('M')
if(isValid)
A(name)
else
B(name)
return isValid;
})
Upvotes: 0