From d697fd0a975026c1c34d70490ce9eddbcad765bc Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Sun, 27 May 2018 15:03:03 +0100 Subject: [PATCH] Implement IteratorExt::choose --- src/seq.rs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/seq.rs b/src/seq.rs index b327463bfa..0d07c215ab 100644 --- a/src/seq.rs +++ b/src/seq.rs @@ -123,10 +123,24 @@ pub trait IteratorExt: Iterator + Sized { /// Complexity is `O(n)`, where `n` is the length of the iterator. /// This likely consumes multiple random numbers, but the exact number /// is unspecified. - fn choose(self, rng: &mut R) -> Option + fn choose(mut self, rng: &mut R) -> Option where R: Rng + ?Sized { - unimplemented!() + if let Some(elem) = self.next() { + let mut result = elem; + + // Continue until the iterator is exhausted + for (i, elem) in self.enumerate() { + let k = rng.gen_range(0, i + 2); + if k == 0 { + result = elem; + } + } + + Some(result) + } else { + None + } } /// Collects `amount` values at random from the iterator into a supplied @@ -485,7 +499,14 @@ mod test { #[test] fn test_choose() { let mut r = ::test::rng(107); - assert_eq!([1, 1, 1].choose(&mut r).map(|&x|x), Some(1)); + assert_eq!([1, 1, 1].choose(&mut r), Some(&1)); + + let mut v = [2]; + v.choose_mut(&mut r).map(|x| *x = 5); + assert_eq!(v[0], 5); + + let v = [3, 3, 3, 3]; + assert_eq!(v.iter().choose(&mut r), Some(&3)); let v: &[isize] = &[]; assert_eq!(v.choose(&mut r), None);