Skip to content
This repository was archived by the owner on Dec 29, 2021. It is now read-only.

Commit 8d577ff

Browse files
committed
functions::array::array_sort
1 parent 24a0d63 commit 8d577ff

File tree

1 file changed

+77
-1
lines changed

1 file changed

+77
-1
lines changed

src/functions/array.rs

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,38 @@ impl ArrayFunctions {
150150
Ok(b.finish())
151151
}
152152
fn array_repeat() {}
153-
fn array_sort() {}
153+
154+
/// Sorts the input array in ascending order.
155+
///
156+
/// TODO: document null treatment, and make it behave like Spark does.
157+
fn array_sort<T>(array: &ListArray) -> Result<ListArray, ArrowError>
158+
where
159+
T: ArrowPrimitiveType + ArrowNumericType,
160+
T::Native: std::cmp::PartialEq<T::Native> + std::cmp::Ord,
161+
{
162+
let values_builder: PrimitiveBuilder<T> = PrimitiveBuilder::new(array.values().len());
163+
let mut b = ListBuilder::new(values_builder);
164+
// get array datatype so we can downcast appropriately
165+
let data_type = array.value_type();
166+
for i in 0..array.len() {
167+
if array.is_null(i) {
168+
b.append(true)?
169+
} else {
170+
let values = array.values();
171+
let values = values.as_any().downcast_ref::<PrimitiveArray<T>>().unwrap();
172+
let values = values.value_slice(
173+
array.value_offset(i) as usize,
174+
array.value_length(i) as usize,
175+
);
176+
let mut v = values.to_vec();
177+
v.sort();
178+
// TODO check how nulls are treated here
179+
v.iter().for_each(|x| b.values().append_value(*x).unwrap());
180+
b.append(true)?;
181+
}
182+
}
183+
Ok(b.finish())
184+
}
154185
fn array_union() {}
155186
fn arrays_overlap() {}
156187
fn arrays_zip() {}
@@ -306,6 +337,7 @@ mod tests {
306337
let values = b.values();
307338
let values = values.as_any().downcast_ref::<PrimitiveArray<Int64Type>>().unwrap();
308339

340+
assert_eq!(6, b.len());
309341
assert_eq!(13, values.len());
310342
assert_eq!(0, b.value_offset(0));
311343
assert_eq!(3, b.value_offset(1));
@@ -314,4 +346,48 @@ mod tests {
314346
assert_eq!(10, b.value_offset(4));
315347
assert_eq!(11, b.value_offset(5));
316348
}
349+
350+
#[test]
351+
fn test_array_sort() {
352+
// Construct a value array
353+
let value_data =
354+
Int64Array::from(vec![0, 0, 0, 1, 2, 1, 3, 4, 5, 1, 3, 2, 3, 2, 8, 3]).data();
355+
356+
let value_offsets = Buffer::from(&[0, 3, 6, 8, 12, 14, 16].to_byte_slice());
357+
358+
// Construct a list array from the above two
359+
let list_data_type = DataType::List(Box::new(DataType::Int64));
360+
let list_data = ArrayData::builder(list_data_type.clone())
361+
.len(6)
362+
.add_buffer(value_offsets.clone())
363+
.add_child_data(value_data.clone())
364+
.build();
365+
let list_array = ListArray::from(list_data);
366+
367+
let b = ArrayFunctions::array_sort::<Int64Type>(&list_array).unwrap();
368+
let values = b.values();
369+
let values = values.as_any().downcast_ref::<PrimitiveArray<Int64Type>>().unwrap();
370+
371+
assert_eq!(6, b.len());
372+
assert_eq!(16, values.len());
373+
assert_eq!(0, b.value_offset(0));
374+
assert_eq!(3, b.value_offset(1));
375+
assert_eq!(6, b.value_offset(2));
376+
assert_eq!(8, b.value_offset(3));
377+
assert_eq!(12, b.value_offset(4));
378+
assert_eq!(14, b.value_offset(5));
379+
380+
let expected = Int64Array::from(vec![0, 0, 0, 1, 1, 2, 3, 4, 1, 2, 3, 5, 2, 3, 3, 8]);
381+
for i in 0..b.len() {
382+
let x = values.value_slice(
383+
b.value_offset(i) as usize,
384+
b.value_length(i) as usize
385+
);
386+
let d = expected.value_slice(
387+
b.value_offset(i) as usize,
388+
b.value_length(i) as usize
389+
);
390+
assert_eq!(x, d);
391+
}
392+
}
317393
}

0 commit comments

Comments
 (0)