@@ -12,7 +12,8 @@ use cmp::Ordering;
12
12
use ops:: Try ;
13
13
14
14
use super :: { AlwaysOk , LoopState } ;
15
- use super :: { Chain , Cycle , Cloned , Enumerate , Filter , FilterMap , FlatMap , Fuse } ;
15
+ use super :: { Chain , Cycle , Cloned , Enumerate , Filter , FilterMap , Fuse } ;
16
+ use super :: { Flatten , FlatMap , flatten_compat} ;
16
17
use super :: { Inspect , Map , Peekable , Scan , Skip , SkipWhile , StepBy , Take , TakeWhile , Rev } ;
17
18
use super :: { Zip , Sum , Product } ;
18
19
use super :: { ChainState , FromIterator , ZipImpl } ;
@@ -997,11 +998,15 @@ pub trait Iterator {
997
998
/// an extra layer of indirection. `flat_map()` will remove this extra layer
998
999
/// on its own.
999
1000
///
1001
+ /// You can think of [`flat_map(f)`][flat_map] as the semantic equivalent
1002
+ /// of [`map`]ping, and then [`flatten`]ing as in `map(f).flatten()`.
1003
+ ///
1000
1004
/// Another way of thinking about `flat_map()`: [`map`]'s closure returns
1001
1005
/// one item for each element, and `flat_map()`'s closure returns an
1002
1006
/// iterator for each element.
1003
1007
///
1004
1008
/// [`map`]: #method.map
1009
+ /// [`flatten`]: #method.flatten
1005
1010
///
1006
1011
/// # Examples
1007
1012
///
@@ -1021,7 +1026,79 @@ pub trait Iterator {
1021
1026
fn flat_map < U , F > ( self , f : F ) -> FlatMap < Self , U , F >
1022
1027
where Self : Sized , U : IntoIterator , F : FnMut ( Self :: Item ) -> U ,
1023
1028
{
1024
- FlatMap { iter : self , f : f, frontiter : None , backiter : None }
1029
+ FlatMap { inner : flatten_compat ( self . map ( f) ) }
1030
+ }
1031
+
1032
+ /// Creates an iterator that flattens nested structure.
1033
+ ///
1034
+ /// This is useful when you have an iterator of iterators or an iterator of
1035
+ /// things that can be turned into iterators and you want to remove one
1036
+ /// level of indirection.
1037
+ ///
1038
+ /// # Examples
1039
+ ///
1040
+ /// Basic usage:
1041
+ ///
1042
+ /// ```
1043
+ /// #![feature(iterator_flatten)]
1044
+ ///
1045
+ /// let data = vec![vec![1, 2, 3, 4], vec![5, 6]];
1046
+ /// let flattened = data.into_iter().flatten().collect::<Vec<u8>>();
1047
+ /// assert_eq!(flattened, &[1, 2, 3, 4, 5, 6]);
1048
+ /// ```
1049
+ ///
1050
+ /// Mapping and then flattening:
1051
+ ///
1052
+ /// ```
1053
+ /// #![feature(iterator_flatten)]
1054
+ ///
1055
+ /// let words = ["alpha", "beta", "gamma"];
1056
+ ///
1057
+ /// // chars() returns an iterator
1058
+ /// let merged: String = words.iter()
1059
+ /// .map(|s| s.chars())
1060
+ /// .flatten()
1061
+ /// .collect();
1062
+ /// assert_eq!(merged, "alphabetagamma");
1063
+ /// ```
1064
+ ///
1065
+ /// You can also rewrite this in terms of [`flat_map()`] which is preferable
1066
+ /// in this case since that conveys intent clearer:
1067
+ ///
1068
+ /// ```
1069
+ /// let words = ["alpha", "beta", "gamma"];
1070
+ ///
1071
+ /// // chars() returns an iterator
1072
+ /// let merged: String = words.iter()
1073
+ /// .flat_map(|s| s.chars())
1074
+ /// .collect();
1075
+ /// assert_eq!(merged, "alphabetagamma");
1076
+ /// ```
1077
+ ///
1078
+ /// Flattening once only removes one level of nesting:
1079
+ ///
1080
+ /// ```
1081
+ /// #![feature(iterator_flatten)]
1082
+ ///
1083
+ /// let d3 = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]];
1084
+ ///
1085
+ /// let d2 = d3.iter().flatten().collect::<Vec<_>>();
1086
+ /// assert_eq!(d2, [&[1, 2], &[3, 4], &[5, 6], &[7, 8]]);
1087
+ ///
1088
+ /// let d1 = d3.iter().flatten().flatten().collect::<Vec<_>>();
1089
+ /// assert_eq!(d1, [&1, &2, &3, &4, &5, &6, &7, &8]);
1090
+ /// ```
1091
+ ///
1092
+ /// Here we see that `flatten()` does not perform a "deep" flatten.
1093
+ /// Instead, only one level of nesting is removed. That is, if you
1094
+ /// `flatten()` a three-dimensional array the result will be
1095
+ /// two-dimensional and not one-dimensional. To get a one-dimensional
1096
+ /// structure, you have to `flatten()` again.
1097
+ #[ inline]
1098
+ #[ unstable( feature = "iterator_flatten" , issue = "48213" ) ]
1099
+ fn flatten ( self ) -> Flatten < Self >
1100
+ where Self : Sized , Self :: Item : IntoIterator {
1101
+ Flatten { inner : flatten_compat ( self ) }
1025
1102
}
1026
1103
1027
1104
/// Creates an iterator which ends after the first [`None`].
0 commit comments