@@ -60,6 +60,32 @@ pub trait IndexedRandom: Index<usize> {
60
60
}
61
61
}
62
62
63
+ /// Return an iterator which samples from `self` with replacement
64
+ ///
65
+ /// Returns `None` if and only if `self.is_empty()`.
66
+ ///
67
+ /// # Example
68
+ ///
69
+ /// ```
70
+ /// use rand::seq::IndexedRandom;
71
+ ///
72
+ /// let choices = [1, 2, 4, 8, 16, 32];
73
+ /// let mut rng = rand::rng();
74
+ /// for choice in choices.choose_iter(&mut rng).unwrap().take(3) {
75
+ /// println!("{:?}", choice);
76
+ /// }
77
+ /// ```
78
+ fn choose_iter < R > (
79
+ & self ,
80
+ rng : & mut R ,
81
+ ) -> Option < impl Iterator < Item = & Self :: Output > >
82
+ where
83
+ R : Rng + ?Sized ,
84
+ {
85
+ let distr = crate :: distr:: Uniform :: new ( 0 , self . len ( ) ) . ok ( ) ?;
86
+ Some ( rng. sample_iter ( distr) . map ( |i| & self [ i] ) )
87
+ }
88
+
63
89
/// Uniformly sample `amount` distinct elements from self
64
90
///
65
91
/// Chooses `amount` elements from the slice at random, without repetition,
@@ -128,7 +154,7 @@ pub trait IndexedRandom: Index<usize> {
128
154
/// Biased sampling for one element
129
155
///
130
156
/// Returns a reference to one element of the slice, sampled according
131
- /// to the provided weights. Returns `None` only if the slice is empty .
157
+ /// to the provided weights. Returns `None` if and only if `self.is_empty()` .
132
158
///
133
159
/// The specified function `weight` maps each item `x` to a relative
134
160
/// likelihood `weight(x)`. The probability of each item being selected is
@@ -166,9 +192,33 @@ pub trait IndexedRandom: Index<usize> {
166
192
B : SampleBorrow < X > ,
167
193
X : SampleUniform + Weight + PartialOrd < X > ,
168
194
{
169
- use crate :: distr:: { weighted:: WeightedIndex , Distribution } ;
195
+ use crate :: distr:: weighted:: WeightedIndex ;
196
+ let distr = WeightedIndex :: new ( ( 0 ..self . len ( ) ) . map ( |idx| weight ( & self [ idx] ) ) ) ?;
197
+ Ok ( & self [ rng. sample ( distr) ] )
198
+ }
199
+
200
+ /// Biased sampling with replacement
201
+ ///
202
+ /// Returns an iterator which samples elements from `self` according to the
203
+ /// given weights with replacement (i.e. elements may be repeated).
204
+ /// Returns `None` if and only if `self.is_empty()`.
205
+ ///
206
+ /// See also doc for [`Self::choose_weighted`].
207
+ #[ cfg( feature = "alloc" ) ]
208
+ fn choose_weighted_iter < R , F , B , X > (
209
+ & self ,
210
+ rng : & mut R ,
211
+ weight : F ,
212
+ ) -> Result < impl Iterator < Item = & Self :: Output > , WeightError >
213
+ where
214
+ R : Rng + ?Sized ,
215
+ F : Fn ( & Self :: Output ) -> B ,
216
+ B : SampleBorrow < X > ,
217
+ X : SampleUniform + Weight + PartialOrd < X > ,
218
+ {
219
+ use crate :: distr:: weighted:: WeightedIndex ;
170
220
let distr = WeightedIndex :: new ( ( 0 ..self . len ( ) ) . map ( |idx| weight ( & self [ idx] ) ) ) ?;
171
- Ok ( & self [ distr . sample ( rng ) ] )
221
+ Ok ( rng . sample_iter ( distr ) . map ( |i| & self [ i ] ) )
172
222
}
173
223
174
224
/// Biased sampling of `amount` distinct elements
0 commit comments