You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by ne...@apache.org on 2020/11/07 13:20:52 UTC

[arrow] branch master updated: ARROW-10445: [Rust] Added doubleEnded iterator to PrimitiveArrayIter

This is an automated email from the ASF dual-hosted git repository.

nevime pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new 130f6a0  ARROW-10445: [Rust] Added doubleEnded iterator to PrimitiveArrayIter
130f6a0 is described below

commit 130f6a01167c7b42dd140ffab81d2f013ef76515
Author: Jorge C. Leitao <jo...@gmail.com>
AuthorDate: Sat Nov 7 15:20:15 2020 +0200

    ARROW-10445: [Rust] Added doubleEnded iterator to PrimitiveArrayIter
    
    This puts it in line with `array::NullIter`. This PR is complementary to #8561 (which removes `NullIter`), so that the PrimitiveArrayIterator can be reversed in the same way `NullIter` can. Together with #8561, it re-allows Dictionary keys to be iterated backwards.
    
    Closes #8562 from jorgecarleitao/double_ended
    
    Authored-by: Jorge C. Leitao <jo...@gmail.com>
    Signed-off-by: Neville Dipale <ne...@gmail.com>
---
 rust/arrow/src/array/iterator.rs | 52 +++++++++++++++++++++++++++++++---------
 1 file changed, 41 insertions(+), 11 deletions(-)

diff --git a/rust/arrow/src/array/iterator.rs b/rust/arrow/src/array/iterator.rs
index 9cab95c..8b3aba8 100644
--- a/rust/arrow/src/array/iterator.rs
+++ b/rust/arrow/src/array/iterator.rs
@@ -23,11 +23,12 @@ use super::{
 };
 
 /// an iterator that returns Some(T) or None, that can be used on any non-boolean PrimitiveArray
+// Note: This implementation is based on std's [Vec]s' [IntoIter].
 #[derive(Debug)]
 pub struct PrimitiveIter<'a, T: ArrowPrimitiveType> {
     array: &'a PrimitiveArray<T>,
-    i: usize,
-    len: usize,
+    current: usize,
+    current_end: usize,
 }
 
 impl<'a, T: ArrowPrimitiveType> PrimitiveIter<'a, T> {
@@ -35,8 +36,8 @@ impl<'a, T: ArrowPrimitiveType> PrimitiveIter<'a, T> {
     pub fn new(array: &'a PrimitiveArray<T>) -> Self {
         PrimitiveIter::<T> {
             array,
-            i: 0,
-            len: array.len(),
+            current: 0,
+            current_end: array.len(),
         }
     }
 }
@@ -45,20 +46,35 @@ impl<'a, T: ArrowPrimitiveType> std::iter::Iterator for PrimitiveIter<'a, T> {
     type Item = Option<T::Native>;
 
     fn next(&mut self) -> Option<Self::Item> {
-        let i = self.i;
-        if i >= self.len {
+        if self.current == self.current_end {
             None
-        } else if self.array.is_null(i) {
-            self.i += 1;
+        } else if self.array.is_null(self.current) {
+            self.current += 1;
             Some(None)
         } else {
-            self.i += 1;
-            Some(Some(self.array.value(i)))
+            let old = self.current;
+            self.current += 1;
+            Some(Some(self.array.value(old)))
         }
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
-        (self.len, Some(self.len))
+        (self.array.len(), Some(self.array.len()))
+    }
+}
+
+impl<'a, T: ArrowPrimitiveType> std::iter::DoubleEndedIterator for PrimitiveIter<'a, T> {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        if self.current_end == self.current {
+            None
+        } else {
+            self.current_end -= 1;
+            Some(if self.array.is_null(self.current_end) {
+                None
+            } else {
+                Some(self.array.value(self.current_end))
+            })
+        }
     }
 }
 
@@ -185,6 +201,20 @@ mod tests {
     }
 
     #[test]
+    fn test_double_ended() {
+        let array = Int32Array::from(vec![Some(0), None, Some(2), None, Some(4)]);
+        let mut a = array.iter();
+        assert_eq!(a.next(), Some(Some(0)));
+        assert_eq!(a.next(), Some(None));
+        assert_eq!(a.next_back(), Some(Some(4)));
+        assert_eq!(a.next_back(), Some(None));
+        assert_eq!(a.next_back(), Some(Some(2)));
+        // the two sides have met: None is returned by both
+        assert_eq!(a.next_back(), None);
+        assert_eq!(a.next(), None);
+    }
+
+    #[test]
     fn test_string_array_iter_round_trip() {
         let array =
             StringArray::from(vec![Some("a"), None, Some("aaa"), None, Some("aaaaa")]);