Coming from Python and Numpy, a typical feature I find myself using frequently are boolean masks.
Here's an example in Python:
>>> mylist = np.array([50, 12, 100, -5, 73])
>>> mylist == 12
array([False, True, False, False, False]) # A new array that is the result of ..
# .. comparing each element to 12
>>> mylist > 0
array([True, True, True, False, True]) # A new array that is the result of ..
# .. comparing each element to 0
>>> mylist[mylist == 12]
array([12]) # A new array of all values at indexes ..
# .. where the result of `mylist == 12` is True
>>> mask = mylist != 100 # Save a mask
>>> map(foo, mylist[mask]) # Apply `foo` where the mask is truthy
In general when np.array
is indexed by another array of the same size, a new array is returned containing the elements at those indexes where the mask array's value is truthy.
I am able to do something similar with Array.prototype.map
and Array.prototype.filter
in Javascript but it's more verbose and my mask is destroyed.
-> mylist = [50, 12, 100, -5, 73]
-> mylist.map(item => item == 12)
<- [false, true, false, false, false] // mylist == 12
-> mylist.filter(item => item == 12)
<- [12] // mylist[mylist == 12]
-> mask = mylist.map(item => item == 12)
-> mylist.filter(item => mask.unshift())
<- [12] // mylist[mask]
-> mask
<- [] // Mask isn't reusable
Is there a better way of applying masks over arrays in javascript or am I stuck making copies of masks and using filter
and map
each time?
Boolean masking, also called boolean indexing, is a feature in Python NumPy that allows for the filtering of values in numpy arrays.
A masked array is the combination of a standard numpy. ndarray and a mask. A mask is either nomask , indicating that no value of the associated array is invalid, or an array of booleans that determines for each element of the associated array whether the value is valid or not.
To count the true values in an array:Use the filter() method to iterate over the array. Check if each value is equal to true and return the result. Access the length property on the array to get the count of the true values.
Both filter and map create new arrays so they're fine. However, your use of unshift seems to be because you want the index rather than the value. You could pass the index in the call:
var mylist = [50, 12, 100, -5, 73];
var mask = mylist.map(item => item == 12);
var newlist = mylist.filter((item, i) => mask[i]);
console.log(newlist);
or if you don't want to pass more then one value, you could write your own maskFilter method of Array.prototype that takes just a mask instead:
Array.prototype.maskFilter = function(mask) {
return this.filter((item, i) => mask[i]);
}
var mylist = [50, 12, 100, -5, 73];
var mask = mylist.map(item => item == 12);
var newlist = mylist.maskFilter(mask);
console.log(newlist); // [12]
console.log(mylist); // untouched
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With