From 635b7c19669a1affd717cf1597701d029bc3fe45 Mon Sep 17 00:00:00 2001 From: Josh Magarick Date: Wed, 26 Jul 2023 12:33:13 -0700 Subject: [PATCH] fix is_sorted for structs --- polars/polars-ops/src/series/ops/various.rs | 23 ++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/polars/polars-ops/src/series/ops/various.rs b/polars/polars-ops/src/series/ops/various.rs index 5bf22ad0f069..1f537c709ab9 100644 --- a/polars/polars-ops/src/series/ops/various.rs +++ b/polars/polars-ops/src/series/ops/various.rs @@ -70,9 +70,26 @@ pub trait SeriesMethods: SeriesSealed { // Compare adjacent elements with no-copy slices that don't include any nulls let offset = !options.nulls_last as i64 * nc as i64; let (s1, s2) = (s.slice(offset, slen), s.slice(offset + 1, slen)); - match options.descending { - true => Ok(Series::gt_eq(&s1, &s2)?.all()), - false => Ok(Series::lt_eq(&s1, &s2)?.all()), + let cmp_op = match options.descending { + true => Series::gt_eq, + false => Series::lt_eq, + }; + match s.dtype() { + // For structs compare per-field. We don't have to check any types or field names though + // since we're just comparing two offset slices of the same Series. The loop is to both + // short-circuit on false and propagate errors. Maybe there's a way with iterators? + #[cfg(feature = "dtype-struct")] + DataType::Struct(_) => { + let mut struct_cmp = true; + for (l, r) in s1.struct_()?.fields().iter().zip(s2.struct_()?.fields()) { + struct_cmp &= cmp_op(l, r)?.all(); + if !struct_cmp { + break; + } + } + Ok(struct_cmp) + } + _ => Ok(cmp_op(&s1, &s2)?.all()), } } }