Skip to content

Commit a5a70ff

Browse files
author
Jiayu Liu
committed
add more doc test for window::shift
1 parent f41cb17 commit a5a70ff

File tree

1 file changed

+85
-22
lines changed

1 file changed

+85
-22
lines changed

arrow/src/compute/kernels/window.rs

Lines changed: 85 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,10 @@
1717

1818
//! Defines windowing functions, like `shift`ing
1919
20-
use crate::{array::new_null_array, compute::concat};
21-
use num::{abs, clamp};
22-
2320
use crate::array::{Array, ArrayRef};
21+
use crate::{array::new_null_array, compute::concat};
2422
use crate::{array::PrimitiveArray, datatypes::ArrowPrimitiveType, error::Result};
23+
use num::{abs, clamp};
2524

2625
/// Shifts array by defined number of items (to left or right)
2726
/// A positive value for `offset` shifts the array to the right
@@ -33,56 +32,120 @@ use crate::{array::PrimitiveArray, datatypes::ArrowPrimitiveType, error::Result}
3332
/// use arrow::compute::shift;
3433
///
3534
/// let a: Int32Array = vec![Some(1), None, Some(4)].into();
35+
///
3636
/// // shift array 1 element to the right
3737
/// let res = shift(&a, 1).unwrap();
3838
/// let expected: Int32Array = vec![None, Some(1), None].into();
39-
/// assert_eq!(res.as_ref(), &expected)
39+
/// assert_eq!(res.as_ref(), &expected);
40+
///
41+
/// // shift array 1 element to the left
42+
/// let res = shift(&a, -1).unwrap();
43+
/// let expected: Int32Array = vec![None, Some(4), None].into();
44+
/// assert_eq!(res.as_ref(), &expected);
45+
///
46+
/// // shift array 0 element, although not recommended
47+
/// let res = shift(&a, 0).unwrap();
48+
/// let expected: Int32Array = vec![Some(1), None, Some(4)].into();
49+
/// assert_eq!(res.as_ref(), &expected);
50+
///
51+
/// // shift array 3 element tot he right
52+
/// let res = shift(&a, 3).unwrap();
53+
/// let expected: Int32Array = vec![None, None, None].into();
54+
/// assert_eq!(res.as_ref(), &expected);
4055
/// ```
4156
pub fn shift<T>(values: &PrimitiveArray<T>, offset: i64) -> Result<ArrayRef>
4257
where
4358
T: ArrowPrimitiveType,
4459
{
45-
// Compute slice
46-
let slice_offset = clamp(-offset, 0, values.len() as i64) as usize;
47-
let length = values.len() - abs(offset) as usize;
48-
let slice = values.slice(slice_offset, length);
49-
50-
// Generate array with remaining `null` items
51-
let nulls = abs(offset as i64) as usize;
60+
let value_len = values.len() as i64;
61+
if offset == 0 {
62+
Ok(values.slice(0, values.len()))
63+
} else if abs(offset) >= value_len || offset == i64::MIN {
64+
Ok(new_null_array(&T::DATA_TYPE, values.len()))
65+
} else {
66+
let slice_offset = clamp(-offset, 0, value_len) as usize;
67+
let length = values.len() - abs(offset) as usize;
68+
let slice = values.slice(slice_offset, length);
5269

53-
let null_arr = new_null_array(&T::DATA_TYPE, nulls);
70+
// Generate array with remaining `null` items
71+
let nulls = abs(offset) as usize;
72+
let null_arr = new_null_array(&T::DATA_TYPE, nulls);
5473

55-
// Concatenate both arrays, add nulls after if shift > 0 else before
56-
if offset > 0 {
57-
concat(&[null_arr.as_ref(), slice.as_ref()])
58-
} else {
59-
concat(&[slice.as_ref(), null_arr.as_ref()])
74+
// Concatenate both arrays, add nulls after if shift > 0 else before
75+
if offset > 0 {
76+
concat(&[null_arr.as_ref(), slice.as_ref()])
77+
} else {
78+
concat(&[slice.as_ref(), null_arr.as_ref()])
79+
}
6080
}
6181
}
6282

6383
#[cfg(test)]
6484
mod tests {
65-
use crate::array::Int32Array;
66-
6785
use super::*;
86+
use crate::array::Int32Array;
6887

6988
#[test]
7089
fn test_shift_neg() {
7190
let a: Int32Array = vec![Some(1), None, Some(4)].into();
7291
let res = shift(&a, -1).unwrap();
73-
7492
let expected: Int32Array = vec![None, Some(4), None].into();
75-
7693
assert_eq!(res.as_ref(), &expected);
7794
}
7895

7996
#[test]
8097
fn test_shift_pos() {
8198
let a: Int32Array = vec![Some(1), None, Some(4)].into();
8299
let res = shift(&a, 1).unwrap();
83-
84100
let expected: Int32Array = vec![None, Some(1), None].into();
101+
assert_eq!(res.as_ref(), &expected);
102+
}
85103

104+
#[test]
105+
fn test_shift_nil() {
106+
let a: Int32Array = vec![Some(1), None, Some(4)].into();
107+
let res = shift(&a, 0).unwrap();
108+
let expected: Int32Array = vec![Some(1), None, Some(4)].into();
109+
assert_eq!(res.as_ref(), &expected);
110+
}
111+
112+
#[test]
113+
fn test_shift_boundary_pos() {
114+
let a: Int32Array = vec![Some(1), None, Some(4)].into();
115+
let res = shift(&a, 3).unwrap();
116+
let expected: Int32Array = vec![None, None, None].into();
117+
assert_eq!(res.as_ref(), &expected);
118+
}
119+
120+
#[test]
121+
fn test_shift_boundary_neg() {
122+
let a: Int32Array = vec![Some(1), None, Some(4)].into();
123+
let res = shift(&a, -3).unwrap();
124+
let expected: Int32Array = vec![None, None, None].into();
125+
assert_eq!(res.as_ref(), &expected);
126+
}
127+
128+
#[test]
129+
fn test_shift_boundary_neg_min() {
130+
let a: Int32Array = vec![Some(1), None, Some(4)].into();
131+
let res = shift(&a, i64::MIN).unwrap();
132+
let expected: Int32Array = vec![None, None, None].into();
133+
assert_eq!(res.as_ref(), &expected);
134+
}
135+
136+
#[test]
137+
fn test_shift_large_pos() {
138+
let a: Int32Array = vec![Some(1), None, Some(4)].into();
139+
let res = shift(&a, 1000).unwrap();
140+
let expected: Int32Array = vec![None, None, None].into();
141+
assert_eq!(res.as_ref(), &expected);
142+
}
143+
144+
#[test]
145+
fn test_shift_large_neg() {
146+
let a: Int32Array = vec![Some(1), None, Some(4)].into();
147+
let res = shift(&a, -1000).unwrap();
148+
let expected: Int32Array = vec![None, None, None].into();
86149
assert_eq!(res.as_ref(), &expected);
87150
}
88151
}

0 commit comments

Comments
 (0)