From 14293bd18f01b6bd4856816222f808f46603eccd Mon Sep 17 00:00:00 2001 From: futpib Date: Tue, 26 May 2020 10:59:06 +0300 Subject: [PATCH] Add `DoubleEndedIterator` implementation for `Unique` and `UniqueBy` --- src/unique_impl.rs | 32 ++++++++++++++++++++++++++++++++ tests/test_std.rs | 10 ++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/unique_impl.rs b/src/unique_impl.rs index cf8675c18..85d7d9f49 100644 --- a/src/unique_impl.rs +++ b/src/unique_impl.rs @@ -76,6 +76,22 @@ impl Iterator for UniqueBy } } +impl DoubleEndedIterator for UniqueBy + where I: DoubleEndedIterator, + V: Eq + Hash, + F: FnMut(&I::Item) -> V +{ + fn next_back(&mut self) -> Option { + while let Some(v) = self.iter.next_back() { + let key = (self.f)(&v); + if self.used.insert(key, ()).is_none() { + return Some(v); + } + } + None + } +} + impl Iterator for Unique where I: Iterator, I::Item: Eq + Hash + Clone @@ -104,6 +120,22 @@ impl Iterator for Unique } } +impl DoubleEndedIterator for Unique + where I: DoubleEndedIterator, + I::Item: Eq + Hash + Clone +{ + fn next_back(&mut self) -> Option { + while let Some(v) = self.iter.iter.next_back() { + if let Entry::Vacant(entry) = self.iter.used.entry(v) { + let elt = entry.key().clone(); + entry.insert(()); + return Some(elt); + } + } + None + } +} + /// An iterator adapter to filter out duplicate elements. /// /// See [`.unique()`](../trait.Itertools.html#method.unique) for more information. diff --git a/tests/test_std.rs b/tests/test_std.rs index 23e1911e4..848511c65 100644 --- a/tests/test_std.rs +++ b/tests/test_std.rs @@ -59,6 +59,9 @@ fn unique_by() { let xs = ["aaa", "bbbbb", "aa", "ccc", "bbbb", "aaaaa", "cccc"]; let ys = ["aaa", "bbbbb", "ccc"]; it::assert_equal(ys.iter(), xs.iter().unique_by(|x| x[..2].to_string())); + it::assert_equal(ys.iter(), xs.iter().rev().unique_by(|x| x[..2].to_string()).rev()); + let ys_rev = ["cccc", "aaaaa", "bbbb"]; + it::assert_equal(ys_rev.iter(), xs.iter().unique_by(|x| x[..2].to_string()).rev()); } #[test] @@ -66,9 +69,16 @@ fn unique() { let xs = [0, 1, 2, 3, 2, 1, 3]; let ys = [0, 1, 2, 3]; it::assert_equal(ys.iter(), xs.iter().unique()); + it::assert_equal(ys.iter(), xs.iter().rev().unique().rev()); + let ys_rev = [3, 1, 2, 0]; + it::assert_equal(ys_rev.iter(), xs.iter().unique().rev()); + let xs = [0, 1]; let ys = [0, 1]; it::assert_equal(ys.iter(), xs.iter().unique()); + it::assert_equal(ys.iter(), xs.iter().rev().unique().rev()); + let ys_rev = [1, 0]; + it::assert_equal(ys_rev.iter(), xs.iter().unique().rev()); } #[test]