refactoring
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 5 Apr 2025 19:07:28 +0000 (12:07 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 5 Apr 2025 19:07:28 +0000 (12:07 -0700)
rust/pspp/src/output/pivot/output.rs
rust/pspp/src/output/table.rs

index 9849566e9ece2307435c924079722711e29a1e40..53f9f0ba8727e95a39748a28c4d2dcfa82200c67 100644 (file)
@@ -1,6 +1,7 @@
-use std::sync::Arc;
+use std::{ops::Range, sync::Arc};
 
 use enum_map::{enum_map, EnumMap};
+use itertools::Itertools;
 use smallvec::{SmallVec, ToSmallVec};
 
 use crate::output::{
@@ -455,32 +456,27 @@ fn compose_headings(
         .filter(|(_, d)| !d.hide_all_labels)
     {
         for row_ofs in 0..d.label_depth() {
-            let mut x1 = 0;
-            while x1 < n_columns {
-                let Some(c): Option<Category> = find_category(
+            // Find all the categories, dropping columns without a category.
+            let categories = (0..n_columns).filter_map(|x| {
+                find_category(
                     d,
                     dim_index,
-                    column_enumeration.get(x1),
+                    column_enumeration.get(x),
                     d.label_depth() - row_ofs - 1,
-                ) else {
-                    x1 += 1;
-                    continue;
-                };
-
-                let mut x2 = x1 + 1;
-                while x2 < n_columns && !vrules[x2] {
-                    let c2 = find_category(
-                        d,
-                        dim_index,
-                        column_enumeration.get(x2),
-                        d.label_depth() - row_ofs - 1,
-                    );
-                    if c2.as_ref().is_none_or(|c2| !c.ptr_eq(c2)) {
-                        break;
-                    }
-                    x2 += 1;
+                )
+                .map(|c| (x..x + 1, c))
+            });
+
+            // Merge adjacent identical categories.
+            let categories = categories.coalesce(|(a_r, a), (b_r, b)| {
+                if a.ptr_eq(&b) {
+                    Ok((a_r.start..b_r.end, a))
+                } else {
+                    Err(((a_r, a), (b_r, b)))
                 }
+            });
 
+            for (Range { start: x1, end: x2 }, c) in categories {
                 let y1 = top_row + row_ofs;
                 let y2 = y1 + c.extra_depth() + 1;
                 let is_outer_row = y1 == 0;
@@ -554,7 +550,6 @@ fn compose_headings(
                             h_ofs..table.n[h],
                         );
                     }
-                    x1 = x2;
                 }
             }
 
index 7d6443bcdf21367c19a21ec9b0aa4ba0d927a6c7..2ca155ef622e53cb0e12e305868b41508d9a5c0b 100644 (file)
@@ -240,18 +240,12 @@ impl Table {
     }
 
     pub fn h_line(&mut self, border: Border, x: Range<usize>, y: usize) {
-        debug_assert!(y <= self.n.y());
-        debug_assert!(x.start <= x.end);
-        debug_assert!(x.end <= self.n.x());
         for x in x {
             self.rules[Axis2::Y][[x, y]] = border;
         }
     }
 
     pub fn v_line(&mut self, border: Border, x: usize, y: Range<usize>) {
-        debug_assert!(x <= self.n.x());
-        debug_assert!(y.start <= y.end);
-        debug_assert!(y.end <= self.n.y());
         for y in y {
             self.rules[Axis2::X][[x, y]] = border;
         }