@@ -638,6 +638,25 @@ pub type Ixs = isize;
638
638
/// - `B @ &A` which consumes `B`, updates it with the result, and returns it
639
639
/// - `C @= &A` which performs an arithmetic operation in place
640
640
///
641
+ /// Note that the element type needs to implement the operator trait and the
642
+ /// `Clone` trait.
643
+ ///
644
+ /// ```
645
+ /// use ndarray::{array, ArrayView1};
646
+ ///
647
+ /// let owned1 = array![1, 2];
648
+ /// let owned2 = array![3, 4];
649
+ /// let view1 = ArrayView1::from(&[5, 6]);
650
+ /// let view2 = ArrayView1::from(&[7, 8]);
651
+ /// let mut mutable = array![9, 10];
652
+ ///
653
+ /// let sum1 = &view1 + &view2; // Allocates a new array. Note the explicit `&`.
654
+ /// // let sum2 = view1 + &view2; // This doesn't work because `view1` is not an owned array.
655
+ /// let sum3 = owned1 + view1; // Consumes `owned1`, updates it, and returns it.
656
+ /// let sum4 = owned2 + &view2; // Consumes `owned2`, updates it, and returns it.
657
+ /// mutable += &view2; // Updates `mutable` in-place.
658
+ /// ```
659
+ ///
641
660
/// ### Binary Operators with Array and Scalar
642
661
///
643
662
/// The trait [`ScalarOperand`](trait.ScalarOperand.html) marks types that can be used in arithmetic
@@ -920,7 +939,8 @@ pub type Ixs = isize;
920
939
/// <sup><a name="req_contig">3</a></sup>Works only if the array is contiguous.
921
940
///
922
941
/// The table above does not include all the constructors; it only shows
923
- /// conversions to/from `Vec`s/slices. See below for more constructors.
942
+ /// conversions to/from `Vec`s/slices. See
943
+ /// [below](#constructor-methods-for-owned-arrays) for more constructors.
924
944
///
925
945
/// [ArrayView::reborrow()]: type.ArrayView.html#method.reborrow
926
946
/// [ArrayViewMut::reborrow()]: type.ArrayViewMut.html#method.reborrow
@@ -933,6 +953,101 @@ pub type Ixs = isize;
933
953
/// [.view()]: #method.view
934
954
/// [.view_mut()]: #method.view_mut
935
955
///
956
+ /// ### Conversions from Nested `Vec`s/`Array`s
957
+ ///
958
+ /// It's generally a good idea to avoid nested `Vec`/`Array` types, such as
959
+ /// `Vec<Vec<A>>` or `Vec<Array2<A>>` because:
960
+ ///
961
+ /// * they require extra heap allocations compared to a single `Array`,
962
+ ///
963
+ /// * they can scatter data all over memory (because of multiple allocations),
964
+ ///
965
+ /// * they cause unnecessary indirection (traversing multiple pointers to reach
966
+ /// the data),
967
+ ///
968
+ /// * they don't enforce consistent shape within the nested
969
+ /// `Vec`s/`ArrayBase`s, and
970
+ ///
971
+ /// * they are generally more difficult to work with.
972
+ ///
973
+ /// The most common case where users might consider using nested
974
+ /// `Vec`s/`Array`s is when creating an array by appending rows/subviews in a
975
+ /// loop, where the rows/subviews are computed within the loop. However, there
976
+ /// are better ways than using nested `Vec`s/`Array`s.
977
+ ///
978
+ /// If you know ahead-of-time the shape of the final array, the cleanest
979
+ /// solution is to allocate the final array before the loop, and then assign
980
+ /// the data to it within the loop, like this:
981
+ ///
982
+ /// ```rust
983
+ /// use ndarray::{array, Array2, Axis};
984
+ ///
985
+ /// let mut arr = Array2::zeros((2, 3));
986
+ /// for (i, mut row) in arr.axis_iter_mut(Axis(0)).enumerate() {
987
+ /// // Perform calculations and assign to `row`; this is a trivial example:
988
+ /// row.fill(i);
989
+ /// }
990
+ /// assert_eq!(arr, array![[0, 0, 0], [1, 1, 1]]);
991
+ /// ```
992
+ ///
993
+ /// If you don't know ahead-of-time the shape of the final array, then the
994
+ /// cleanest solution is generally to append the data to a flat `Vec`, and then
995
+ /// convert it to an `Array` at the end with
996
+ /// [`::from_shape_vec()`](#method.from_shape_vec). You just have to be careful
997
+ /// that the layout of the data (the order of the elements in the flat `Vec`)
998
+ /// is correct.
999
+ ///
1000
+ /// ```rust
1001
+ /// use ndarray::{array, Array2};
1002
+ ///
1003
+ /// # fn main() -> Result<(), Box<std::error::Error>> {
1004
+ /// let ncols = 3;
1005
+ /// let mut data = Vec::new();
1006
+ /// let mut nrows = 0;
1007
+ /// for i in 0..2 {
1008
+ /// // Compute `row` and append it to `data`; this is a trivial example:
1009
+ /// let row = vec![i; ncols];
1010
+ /// data.extend_from_slice(&row);
1011
+ /// nrows += 1;
1012
+ /// }
1013
+ /// let arr = Array2::from_shape_vec((nrows, ncols), data)?;
1014
+ /// assert_eq!(arr, array![[0, 0, 0], [1, 1, 1]]);
1015
+ /// # Ok(())
1016
+ /// # }
1017
+ /// ```
1018
+ ///
1019
+ /// If neither of these options works for you, and you really need to convert
1020
+ /// nested `Vec`/`Array` instances to an `Array`, the cleanest solution is
1021
+ /// generally to use
1022
+ /// [`Iterator::flatten()`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.flatten)
1023
+ /// to get a flat `Vec`, and then convert the `Vec` to an `Array` with
1024
+ /// [`::from_shape_vec()`](#method.from_shape_vec), like this:
1025
+ ///
1026
+ /// ```rust
1027
+ /// use ndarray::{array, Array2, Array3};
1028
+ ///
1029
+ /// # fn main() -> Result<(), Box<std::error::Error>> {
1030
+ /// let nested: Vec<Array2<i32>> = vec![
1031
+ /// array![[1, 2, 3], [4, 5, 6]],
1032
+ /// array![[7, 8, 9], [10, 11, 12]],
1033
+ /// ];
1034
+ /// let inner_shape = nested[0].dim();
1035
+ /// let shape = (nested.len(), inner_shape.0, inner_shape.1);
1036
+ /// let flat: Vec<i32> = nested.iter().flatten().cloned().collect();
1037
+ /// let arr = Array3::from_shape_vec(shape, flat)?;
1038
+ /// assert_eq!(arr, array![
1039
+ /// [[1, 2, 3], [4, 5, 6]],
1040
+ /// [[7, 8, 9], [10, 11, 12]],
1041
+ /// ]);
1042
+ /// # Ok(())
1043
+ /// # }
1044
+ /// ```
1045
+ ///
1046
+ /// Note that this implementation assumes that the nested `Vec`s are all the
1047
+ /// same shape and that the `Vec` is non-empty. Depending on your application,
1048
+ /// it may be a good idea to add checks for these assumptions and possibly
1049
+ /// choose a different way to handle the empty case.
1050
+ ///
936
1051
// # For implementors
937
1052
//
938
1053
// All methods must uphold the following constraints:
0 commit comments