@@ -150,7 +150,38 @@ impl ArrayFunctions {
150
150
Ok ( b. finish ( ) )
151
151
}
152
152
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
+ }
154
185
fn array_union ( ) { }
155
186
fn arrays_overlap ( ) { }
156
187
fn arrays_zip ( ) { }
@@ -306,6 +337,7 @@ mod tests {
306
337
let values = b. values ( ) ;
307
338
let values = values. as_any ( ) . downcast_ref :: < PrimitiveArray < Int64Type > > ( ) . unwrap ( ) ;
308
339
340
+ assert_eq ! ( 6 , b. len( ) ) ;
309
341
assert_eq ! ( 13 , values. len( ) ) ;
310
342
assert_eq ! ( 0 , b. value_offset( 0 ) ) ;
311
343
assert_eq ! ( 3 , b. value_offset( 1 ) ) ;
@@ -314,4 +346,48 @@ mod tests {
314
346
assert_eq ! ( 10 , b. value_offset( 4 ) ) ;
315
347
assert_eq ! ( 11 , b. value_offset( 5 ) ) ;
316
348
}
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
+ }
317
393
}
0 commit comments