Skip to main content

ferray_ma/
filled.rs

1// ferray-ma: filled and compressed (REQ-5, REQ-6)
2
3use ferray_core::Array;
4use ferray_core::dimension::{Dimension, Ix1};
5use ferray_core::dtype::Element;
6use ferray_core::error::FerrayResult;
7
8use crate::MaskedArray;
9
10impl<T, D> MaskedArray<T, D>
11where
12    T: Element + Copy,
13    D: Dimension,
14{
15    /// Return a regular array with masked positions replaced by `fill_value`.
16    ///
17    /// Unmasked positions retain their original data values.
18    ///
19    /// # Errors
20    /// Returns an error only for internal failures.
21    pub fn filled(&self, fill_value: T) -> FerrayResult<Array<T, D>> {
22        let data: Vec<T> = self
23            .data()
24            .iter()
25            .zip(self.mask().iter())
26            .map(|(v, m)| if *m { fill_value } else { *v })
27            .collect();
28        Array::from_vec(self.dim().clone(), data)
29    }
30
31    /// Return a regular array with masked positions replaced by the array's
32    /// stored [`MaskedArray::fill_value`].
33    ///
34    /// Equivalent to `NumPy`'s `arr.filled()` with no argument. Use [`MaskedArray::filled`]
35    /// to override the fill value for a single call.
36    ///
37    /// # Errors
38    /// Returns an error only for internal failures.
39    pub fn filled_default(&self) -> FerrayResult<Array<T, D>> {
40        self.filled(self.fill_value)
41    }
42
43    /// Return a 1-D array containing only the unmasked elements.
44    ///
45    /// The order is the logical (row-major) iteration order of the
46    /// original array, with masked elements removed.
47    ///
48    /// # Errors
49    /// Returns an error only for internal failures.
50    pub fn compressed(&self) -> FerrayResult<Array<T, Ix1>> {
51        let data: Vec<T> = self
52            .data()
53            .iter()
54            .zip(self.mask().iter())
55            .filter(|(_, m)| !**m)
56            .map(|(v, _)| *v)
57            .collect();
58        let len = data.len();
59        Array::from_vec(Ix1::new([len]), data)
60    }
61}