arr_rs/core/operations/
manipulate.rs

1use std::cmp::Ordering;
2
3use crate::{
4    core::prelude::*,
5    errors::prelude::*,
6    extensions::prelude::*,
7    validators::prelude::*,
8};
9use crate::prelude::Numeric;
10
11/// `ArrayTrait` - Array Manipulate functions
12pub trait ArrayManipulate<T: ArrayElement> where Array<T>: Sized + Clone {
13
14    /// Insert values along the given axis for the given indices
15    ///
16    /// # Arguments
17    ///
18    /// * `index` - indices before which values is inserted
19    /// * `values` - vector representing values to insert into array
20    /// * `axis` - axis along which to insert values. if None, then array is flattened first
21    ///
22    /// # Examples
23    ///
24    /// ```
25    /// use arr_rs::prelude::*;
26    ///
27    /// let arr = Array::new(vec![1., 2., 3., 4.], vec![4]).insert(&[1], &Array::single(1.).unwrap(), None);
28    /// assert_eq!(array!(f64, [1., 1., 2., 3., 4.]), arr);
29    /// let arr = Array::new(vec![1., 2., 3., 4.], vec![4]).insert(&[1, 3], &Array::single(1.).unwrap(), None);
30    /// assert_eq!(array!(f64, [1., 1., 2., 3., 1., 4.]), arr);
31    /// ```
32    ///
33    /// # Errors
34    ///
35    /// may returns `ArrayError`
36    fn insert(&self, indices: &[usize], values: &Array<T>, axis: Option<usize>) -> Result<Array<T>, ArrayError>;
37
38    /// Delete values along the given axis
39    ///
40    /// # Arguments
41    ///
42    /// * `indices` - vector representing values to delete from array
43    /// * `axis` - axis along which to find unique values. if None, then array is flattened first
44    ///
45    /// # Examples
46    ///
47    /// ```
48    /// use arr_rs::prelude::*;
49    ///
50    /// let arr = Array::new(vec![1., 2., 3., 4.], vec![4]).delete(&[1], None);
51    /// assert_eq!(array!(f64, [1., 3., 4.]), arr);
52    /// let arr = Array::new(vec![1., 2., 3., 4.], vec![4]).delete(&[2, 3], None);
53    /// assert_eq!(array!(f64, [1., 2.]), arr);
54    /// ```
55    ///
56    /// # Errors
57    ///
58    /// may returns `ArrayError`
59    fn delete(&self, indices: &[usize], axis: Option<usize>) -> Result<Array<T>, ArrayError>;
60
61    /// Append values to the end of an array
62    ///
63    /// # Arguments
64    ///
65    /// * `values` - vector representing values to append to array
66    /// * `axis` - axis along which to append values. if None, then array is flattened first
67    ///
68    /// # Examples
69    ///
70    /// ```
71    /// use arr_rs::prelude::*;
72    ///
73    /// let arr = Array::new(vec![1., 2., 3., 4.], vec![4]).append(&Array::single(1.).unwrap(), None);
74    /// assert_eq!(array!(f64, [1., 2., 3., 4., 1.]), arr);
75    /// let arr = Array::new(vec![1., 2., 3., 4.], vec![4]).append(&Array::flat(vec![1., 3.]).unwrap(), None);
76    /// assert_eq!(array!(f64, [1., 2., 3., 4., 1., 3.]), arr);
77    /// ```
78    ///
79    /// # Errors
80    ///
81    /// may returns `ArrayError`
82    fn append(&self, values: &Array<T>, axis: Option<usize>) -> Result<Array<T>, ArrayError>;
83
84    /// Reshapes an array
85    ///
86    /// # Arguments
87    ///
88    /// * `shape` - vector representing new array shape
89    ///
90    /// # Examples
91    ///
92    /// ```
93    /// use arr_rs::prelude::*;
94    ///
95    /// let arr: Array<f64> = Array::new(vec![1., 2., 3., 4.], vec![4]).unwrap();
96    /// assert_eq!(array!(f64, [1., 2., 3., 4.]).unwrap(), arr);
97    /// let arr = arr.reshape(&[2, 2]);
98    /// assert_eq!(array!(f64, [[1., 2.], [3., 4.]]), arr);
99    /// ```
100    ///
101    /// # Errors
102    ///
103    /// may returns `ArrayError`
104    fn reshape(&self, shape: &[usize]) -> Result<Array<T>, ArrayError>;
105
106    /// Resizes an array,
107    ///
108    /// # Arguments
109    ///
110    /// * `shape` - vector representing new array shape
111    ///
112    /// # Examples
113    ///
114    /// ```
115    /// use arr_rs::prelude::*;
116    ///
117    /// let arr = Array::new(vec![1., 2., 3., 4.], vec![4]);
118    /// assert_eq!(array!(f64, [1, 2, 3, 4]), arr);
119    /// let array = arr.resize(&[2, 2]);
120    /// assert_eq!(array!(f64, [[1, 2], [3, 4]]), array);
121    /// let array = arr.resize(&[4]);
122    /// assert_eq!(array!(f64, [1, 2, 3, 4]), array);
123    /// let array = arr.resize(&[8]);
124    /// assert_eq!(array!(f64, [1, 2, 3, 4, 1, 2, 3, 4]), array);
125    /// ```
126    ///
127    /// # Errors
128    ///
129    /// may returns `ArrayError`
130    fn resize(&self, shape: &[usize]) -> Result<Array<T>, ArrayError>;
131
132    /// Find the unique elements of an array
133    ///
134    /// # Arguments
135    ///
136    /// * `axis` - the axis along which to split. optional, if None, array will be flattened
137    ///
138    /// # Examples
139    ///
140    /// ```
141    /// use arr_rs::prelude::*;
142    ///
143    /// let arr = Array::new(vec![1, 1, 2, 3, 3, 4], vec![6]).unwrap();
144    /// assert_eq!(array!(i32, [1, 2, 3, 4]), arr.unique(None));
145    /// let arr = Array::new(vec![1, 2, 3, 2, 1], vec![5]).unwrap();
146    /// assert_eq!(array!(i32, [1, 2, 3]), arr.unique(None));
147    /// ```
148    ///
149    /// # Errors
150    ///
151    /// may returns `ArrayError`
152    fn unique(&self, axis: Option<isize>) -> Result<Array<T>, ArrayError>;
153
154    /// Return a contiguous flattened array
155    ///
156    /// # Examples
157    ///
158    /// ```
159    /// use arr_rs::prelude::*;
160    ///
161    /// let expected = vec![8];
162    ///
163    /// let arr_1 = Array::new(vec![1,2,3,4,5,6,7,8], vec![2, 4]).unwrap();
164    /// assert_eq!(expected, arr_1.ravel().get_shape().unwrap());
165    ///
166    /// let arr_2 = Array::new(vec![1,2,3,4,5,6,7,8], vec![4, 2]).unwrap();
167    /// assert_eq!(expected, arr_2.ravel().get_shape().unwrap());
168    ///
169    /// let arr_3 = Array::new(vec![1,2,3,4,5,6,7,8], vec![2, 2, 2]).unwrap();
170    /// assert_eq!(expected, arr_3.ravel().get_shape().unwrap());
171    /// ```
172    ///
173    /// # Errors
174    ///
175    /// may returns `ArrayError`
176    fn ravel(&self) -> Result<Array<T>, ArrayError>;
177
178    /// Convert array to at least n dimension
179    ///
180    /// # Arguments
181    ///
182    /// * `n` - desired dimension
183    ///
184    /// # Examples
185    ///
186    /// ```
187    /// use arr_rs::prelude::*;
188    ///
189    /// let arr = Array::new(vec![1], vec![1]).unwrap();
190    /// assert_eq!(array!(i32, [[1]]), arr.atleast(2));
191    /// assert_eq!(array!(i32, [[[1]]]), arr.atleast(3));
192    /// ```
193    ///
194    /// # Errors
195    ///
196    /// may returns `ArrayError`
197    fn atleast(&self, n: usize) -> Result<Array<T>, ArrayError>;
198
199    /// Trim the leading and/or trailing zeros from a 1D array
200    ///
201    /// # Examples
202    ///
203    /// ```
204    /// use arr_rs::prelude::*;
205    ///
206    /// let arr = Array::flat(vec![0, 0, 1, 2, 3, 4, 0, 0]);
207    /// assert_eq!(array!(i32, [1, 2, 3, 4]), arr.trim_zeros());
208    /// ```
209    ///
210    /// # Errors
211    ///
212    /// may returns `ArrayError`
213    fn trim_zeros(&self) -> Result<Array<T>, ArrayError>;
214
215    /// Performs cycle().take(n), returning flattened array
216    ///
217    /// # Arguments
218    ///
219    /// n: number of elements to take
220    ///
221    /// # Examples
222    ///
223    /// ```
224    /// use arr_rs::prelude::*;
225    ///
226    /// let arr = Array::flat(vec![1, 2, 3, 4]);
227    /// assert_eq!(array!(i32, [1, 2]), arr.cycle_take(2));
228    /// ```
229    ///
230    /// # Errors
231    ///
232    /// may returns `ArrayError`
233    fn cycle_take(&self, n: usize) -> Result<Array<T>, ArrayError>;
234}
235
236impl <T: ArrayElement> ArrayManipulate<T> for Array<T> {
237
238    fn insert(&self, indices: &[usize], values: &Self, axis: Option<usize>) -> Result<Self, ArrayError> {
239        if indices.iter().any(|&i| i > self.shape[axis.unwrap_or(0)]) { return Err(ArrayError::OutOfBounds { value: "index" }) }
240        values.ndim()?.is_dim_supported(&(1 ..= self.ndim()?).collect::<Vec<usize>>())?;
241
242        if let Some(axis) = axis {
243            vec![indices.len()].is_broadcastable(&self.get_shape()?)?;
244            let mut arrays = self.split_axis(axis)?;
245            let self_rem = self.get_shape()?.remove_at(axis);
246            let self_rem_len = self_rem.into_iter().product::<usize>();
247            let mut values = values.to_array_ndim(self.ndim()?)?;
248            let values_shape_tmp = values.get_shape()?.swap_ext(0, axis);
249
250            for i in (0..self.ndim()?).collect::<Vec<usize>>().remove_at(axis).reverse_ext() {
251                let self_shape_at_i = self.get_shape()?[i];
252                if values_shape_tmp[i] > self_shape_at_i || self_shape_at_i % values_shape_tmp[i] != 0 {
253                    return Err(ArrayError::BroadcastShapeMismatch)
254                } else if values_shape_tmp[i] < self_shape_at_i {
255                    values = values
256                        .repeat(&[self_shape_at_i / values_shape_tmp[i]], Some(0))?
257                        .to_array_ndim(self.ndim()?)?;
258                }
259            };
260
261            let mut values =
262                if indices.len() > 1 {
263                    let values =
264                        if values.len()? == self_rem_len { values.repeat(&[indices.len()], Some(0))? }
265                        else { values };
266                    values.moveaxis(vec![axis.to_isize()], vec![0])
267                        .ravel()
268                        .split(indices.len(), None)?
269                } else { vec![values] };
270
271            for (i, v) in indices.to_vec().reverse_ext().into_iter().zip(values.reverse_ext()) {
272                arrays.insert(i, v.clone());
273            }
274
275            let partial = arrays.into_iter()
276                .map(|arr| arr.get_elements())
277                .collect::<Vec<Result<Vec<T>, _>>>()
278                .has_error()?.into_iter()
279                .flat_map(Result::unwrap)
280                .collect::<Self>();
281            let new_shape = self.get_shape()?
282                .update_at(axis, partial.len()? / self_rem_len)
283                .swap_ext(0, axis);
284            let partial = partial.reshape(&new_shape)?;
285            let transpose_shape = (1..self.ndim()?.to_isize()).collect::<Vec<isize>>().insert_at(axis, 0);
286            partial.transpose(Some(transpose_shape))
287        } else {
288            values.ndim()?.is_dim_supported(&[1])?;
289            let (indices, values) = Array::broadcast_h2(&Array::flat(indices.to_vec())?, &values.ravel()?)?;
290            let values = values.get_elements()?;
291            let mut elements = self.get_elements()?;
292
293            indices.get_elements()?.into_iter()
294                .zip(&values)
295                .sorted_by(|(a, _), (b, _)| a.cmp(b)).rev()
296                .for_each(|(i, v)| elements.insert(i, v.clone()));
297            elements.to_array()
298        }
299    }
300
301    fn delete(&self, indices: &[usize], axis: Option<usize>) -> Result<Self, ArrayError> {
302        let mut indices = indices.to_vec();
303        indices.sort_unstable();
304        indices.dedup();
305        indices = indices.reverse_ext();
306
307        if let Some(axis) = axis {
308            self.apply_along_axis(axis, |arr| arr.delete(&indices, None))
309        } else {
310            let mut elements = self.get_elements()?;
311            if indices.iter().any(|&i| i >= elements.len()) { return Err(ArrayError::OutOfBounds { value: "index" }) }
312            for &i in &indices { elements.remove(i); }
313            elements.to_array()
314        }
315    }
316
317    fn append(&self, values: &Self, axis: Option<usize>) -> Result<Self, ArrayError> {
318        if let Some(axis) = axis {
319            self.axis_in_bounds(axis)?;
320            if self.ndim().is_equal(&values.ndim()).is_err() {
321                return Err(ArrayError::ParameterError { param: "values", message: "input array should have the same dimension as the original one", })
322            } else if self.get_shape()?.remove_at(axis).is_equal(&values.get_shape()?.remove_at(axis)).is_err() {
323                return Err(ArrayError::ParameterError { param: "axis", message: "input array dimensions for the concatenation axis must match exactly", })
324            }
325
326            let mut arrays = self.split_axis(axis)?;
327            let self_rem = self.get_shape()?.remove_at(axis);
328            let self_rem_len = self_rem.into_iter().product::<usize>();
329            let values = values.split_axis(axis)?;
330            arrays.extend_from_slice(&values);
331            let array = arrays.into_iter().flatten().collect::<Self>();
332            let new_shape = self.get_shape()?.update_at(axis, array.len()? / self_rem_len);
333            let tmp_shape = new_shape.clone().swap_ext(0, axis);
334            let transpose_shape = (1..self.ndim()?.to_isize()).collect::<Vec<isize>>().insert_at(axis, 0);
335            array.reshape(&tmp_shape).transpose(Some(transpose_shape)).reshape(&new_shape)
336        } else {
337            let mut elements = self.get_elements()?;
338            elements.extend_from_slice(&values.get_elements()?);
339            elements.to_array()
340        }
341    }
342
343    fn reshape(&self, shape: &[usize]) -> Result<Self, ArrayError> {
344        shape.to_vec().matches_values_len(&self.get_elements()?)?;
345        Self::new(self.elements.clone(), shape.to_vec())
346    }
347
348    fn resize(&self, shape: &[usize]) -> Result<Self, ArrayError> {
349        self.get_elements()?.into_iter().cycle()
350            .take(shape.iter().product::<usize>())
351            .collect::<Self>()
352            .reshape(shape)
353    }
354
355    fn unique(&self, axis: Option<isize>) -> Result<Self, ArrayError> {
356        if let Some(axis) = axis {
357            let axis = self.normalize_axis(axis);
358            self.apply_along_axis(axis, |arr| arr.unique(None))
359        } else {
360            let mut new_elements = self.get_elements()?.into_iter()
361                .sorted_by(|a, b| a.clone().partial_cmp(b).unwrap_or(Ordering::Equal))
362                .collect::<Vec<T>>();
363            new_elements.dedup();
364            new_elements.to_array()
365        }
366    }
367
368    fn ravel(&self) -> Result<Self, ArrayError> {
369        self.elements.to_array()
370    }
371
372    fn atleast(&self, n: usize) -> Result<Self, ArrayError> {
373        match n {
374            0 => Ok(self.clone()),
375            1 => Self::atleast_1d(self),
376            2 => Self::atleast_2d(self),
377            3 => Self::atleast_3d(self),
378            _ => Err(ArrayError::UnsupportedDimension { supported: vec![0, 1, 2, 3] }),
379        }
380    }
381
382    fn trim_zeros(&self) -> Result<Self, ArrayError> {
383        self.is_dim_supported(&[1])?;
384
385        self.get_elements()?
386            .into_iter().rev()
387            .skip_while(|e| e.clone() == T::zero())
388            .collect::<Vec<_>>()
389            .into_iter().rev()
390            .skip_while(|e| e.clone() == T::zero())
391            .collect::<Vec<_>>()
392            .to_array()
393    }
394
395    fn cycle_take(&self, n: usize) -> Result<Self, ArrayError> {
396        Ok(self.into_iter().cycle().take(n).cloned().collect())
397    }
398}
399
400impl <T: ArrayElement> ArrayManipulate<T> for Result<Array<T>, ArrayError> {
401
402    fn insert(&self, indices: &[usize], values: &Array<T>, axis: Option<usize>) -> Self {
403        self.clone()?.insert(indices, values, axis)
404    }
405
406    fn delete(&self, indices: &[usize], axis: Option<usize>) -> Self {
407        self.clone()?.delete(indices, axis)
408    }
409
410    fn append(&self, values: &Array<T>, axis: Option<usize>) -> Self {
411        self.clone()?.append(values, axis)
412    }
413
414    fn reshape(&self, shape: &[usize]) -> Self {
415        self.clone()?.reshape(shape)
416    }
417
418    fn resize(&self, shape: &[usize]) -> Self {
419        self.clone()?.resize(shape)
420    }
421
422    fn unique(&self, axis: Option<isize>) -> Self {
423        self.clone()?.unique(axis)
424    }
425
426    fn ravel(&self) -> Self {
427        self.clone()?.ravel()
428    }
429
430    fn atleast(&self, n: usize) -> Self {
431        self.clone()?.atleast(n)
432    }
433
434    fn trim_zeros(&self) -> Self {
435        self.clone()?.trim_zeros()
436    }
437
438    fn cycle_take(&self, n: usize) -> Self {
439        self.clone()?.cycle_take(n)
440    }
441}
442
443impl <T: ArrayElement> Array<T> {
444
445    fn atleast_1d(&self) -> Result<Self, ArrayError> {
446        if !self.ndim()? >= 1 { Ok(self.clone()) }
447        else { self.reshape(&[1]) }
448    }
449
450    fn atleast_2d(&self) -> Result<Self, ArrayError> {
451        if self.ndim()? >= 2 { Ok(self.clone()) }
452        else {
453            match self.ndim()? {
454                0 => self.reshape(&[1, 1]),
455                1 => self.reshape(&[1, self.get_shape()?[0]]),
456                _ => self.reshape(&[self.get_shape()?[0], 1]),
457            }
458        }
459    }
460
461    fn atleast_3d(&self) -> Result<Self, ArrayError> {
462        if self.ndim()? >= 3 { Ok(self.clone()) }
463        else {
464            match self.ndim()? {
465                0 => self.reshape(&[1, 1, 1]),
466                1 => self.reshape(&[1, self.get_shape()?[0], 1]),
467                2 => self.reshape(&[self.get_shape()?[0], self.get_shape()?[1], 1]),
468                _ => Ok(self.clone()),
469            }
470        }
471    }
472}
473
474impl <T: ArrayElement> Array<T> {
475
476    pub(crate) fn normalize_axis(&self, axis: isize) -> usize {
477        if axis < 0 { (axis + self.ndim().unwrap().to_isize()).to_usize() }
478        else { axis.to_usize() }
479    }
480
481    pub(crate) fn normalize_axis_dim(&self, axis: isize, ndim: usize) -> usize {
482        if axis < 0 { (self.ndim().unwrap().to_isize() + axis + ndim.to_isize()).to_usize() }
483        else { axis.to_usize() }
484    }
485}