@@ -60,6 +60,29 @@ 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 > ( & self , rng : & mut R ) -> Option < impl Iterator < Item = & Self :: Output > >
79
+ where
80
+ R : Rng + ?Sized ,
81
+ {
82
+ let distr = crate :: distr:: Uniform :: new ( 0 , self . len ( ) ) . ok ( ) ?;
83
+ Some ( rng. sample_iter ( distr) . map ( |i| & self [ i] ) )
84
+ }
85
+
63
86
/// Uniformly sample `amount` distinct elements from self
64
87
///
65
88
/// Chooses `amount` elements from the slice at random, without repetition,
@@ -128,7 +151,7 @@ pub trait IndexedRandom: Index<usize> {
128
151
/// Biased sampling for one element
129
152
///
130
153
/// Returns a reference to one element of the slice, sampled according
131
- /// to the provided weights. Returns `None` only if the slice is empty .
154
+ /// to the provided weights. Returns `None` if and only if `self.is_empty()` .
132
155
///
133
156
/// The specified function `weight` maps each item `x` to a relative
134
157
/// likelihood `weight(x)`. The probability of each item being selected is
@@ -166,9 +189,33 @@ pub trait IndexedRandom: Index<usize> {
166
189
B : SampleBorrow < X > ,
167
190
X : SampleUniform + Weight + PartialOrd < X > ,
168
191
{
169
- use crate :: distr:: { weighted:: WeightedIndex , Distribution } ;
192
+ use crate :: distr:: weighted:: WeightedIndex ;
193
+ let distr = WeightedIndex :: new ( ( 0 ..self . len ( ) ) . map ( |idx| weight ( & self [ idx] ) ) ) ?;
194
+ Ok ( & self [ rng. sample ( distr) ] )
195
+ }
196
+
197
+ /// Biased sampling with replacement
198
+ ///
199
+ /// Returns an iterator which samples elements from `self` according to the
200
+ /// given weights with replacement (i.e. elements may be repeated).
201
+ /// Returns `None` if and only if `self.is_empty()`.
202
+ ///
203
+ /// See also doc for [`Self::choose_weighted`].
204
+ #[ cfg( feature = "alloc" ) ]
205
+ fn choose_weighted_iter < R , F , B , X > (
206
+ & self ,
207
+ rng : & mut R ,
208
+ weight : F ,
209
+ ) -> Result < impl Iterator < Item = & Self :: Output > , WeightError >
210
+ where
211
+ R : Rng + ?Sized ,
212
+ F : Fn ( & Self :: Output ) -> B ,
213
+ B : SampleBorrow < X > ,
214
+ X : SampleUniform + Weight + PartialOrd < X > ,
215
+ {
216
+ use crate :: distr:: weighted:: WeightedIndex ;
170
217
let distr = WeightedIndex :: new ( ( 0 ..self . len ( ) ) . map ( |idx| weight ( & self [ idx] ) ) ) ?;
171
- Ok ( & self [ distr . sample ( rng ) ] )
218
+ Ok ( rng . sample_iter ( distr ) . map ( |i| & self [ i ] ) )
172
219
}
173
220
174
221
/// Biased sampling of `amount` distinct elements
0 commit comments