}
}
- fn decode_dimension(
- variables: &[(&Series, usize)],
+ fn decode_dimension<'a>(
+ variables: &[(&'a Series, usize)],
axes: &HashMap<usize, &Axis>,
styles: &HashMap<&str, &Style>,
a: Axis3,
rotate_inner_column_labels: &mut bool,
rotate_outer_row_labels: &mut bool,
footnotes: &pivot::Footnotes,
- ) -> Dimension {
+ dims: &mut Vec<Dim<'a>>,
+ ) {
let base_level = variables[0].1;
let show_label = if let Ok(a) = Axis2::try_from(a)
&& let Some(axis) = axes.get(&(base_level + variables.len()))
.map(|(series, _level)| *series)
.collect::<Vec<_>>();
- // Find the first row for each category, then drop missing
- // categories and count what's left.
- let max_cat = variables[0].max_category().unwrap()/*XXX*/;
- let mut cat_rows = vec![None; max_cat + 1];
- for (index, value) in variables[0].values.iter().enumerate() {
- if let Some(row) = value.category() {
- cat_rows[row].get_or_insert(index);
- }
- }
- let cat_rows = cat_rows.into_iter().flatten().collect::<Vec<_>>();
-
// Make leaf categories.
- let mut cats = Vec::with_capacity(cat_rows.len());
- for (index, cat_row) in cat_rows.into_iter().enumerate() {
- let dv = &variables[0].values[cat_row];
- let name = variables[0].new_name(dv, footnotes);
- cats.push((Category::from(Leaf::new(name)), index..index + 1));
- }
- if cats.is_empty() {
- todo!()
+ let mut coordinate_to_index = HashMap::new();
+ let mut cats = Vec::new();
+ for (index, value) in variables[0].values.iter().enumerate() {
+ let Some(row) = value.category() else {
+ continue;
+ };
+ coordinate_to_index.insert(row, index);
+ let name = variables[0].new_name(value, footnotes);
+ cats.push((Category::from(Leaf::new(name)), cats.len()..cats.len() + 1));
}
// Now group them, in one pass per grouping variable, innermost first.
cats = next_cats;
}
- Dimension::new(
+ let dimension = Dimension::new(
Group::new(
variables[0]
.label
)
.with_multiple(cats.into_iter().map(|(category, _range)| category))
.with_show_label(show_label),
- )
+ );
+ dims.push(Dim {
+ axis: a,
+ dimension: Some(dimension),
+ coordinate: variables[0],
+ coordinate_to_index,
+ });
}
fn decode_dimensions<'a, 'b>(
rotate_outer_row_labels: &mut bool,
footnotes: &pivot::Footnotes,
level_ofs: usize,
- dimensions: &mut Vec<(Axis3, pivot::Dimension)>,
- coordinates: &mut Vec<&'b Series>,
+ dims: &mut Vec<Dim<'b>>,
) {
let variables = variables
.into_iter()
if let Some((var, level)) = var {
dim_vars.push((var, level));
} else if !dim_vars.is_empty() {
- coordinates.push(dim_vars[0].0);
- dimensions.push((
- a,
- decode_dimension(
- &dim_vars,
- axes,
- styles,
- a,
- look,
- rotate_inner_column_labels,
- rotate_outer_row_labels,
- footnotes,
- ),
- ));
- dim_vars.clear();
- }
- }
- if !dim_vars.is_empty() {
- coordinates.push(dim_vars[0].0);
- dimensions.push((
- a,
decode_dimension(
&dim_vars,
axes,
rotate_inner_column_labels,
rotate_outer_row_labels,
footnotes,
- ),
- ));
+ dims,
+ );
+ dim_vars.clear();
+ }
}
+ if !dim_vars.is_empty() {
+ decode_dimension(
+ &dim_vars,
+ axes,
+ styles,
+ a,
+ look,
+ rotate_inner_column_labels,
+ rotate_outer_row_labels,
+ footnotes,
+ dims,
+ );
+ }
+ }
+
+ struct Dim<'a> {
+ axis: Axis3,
+ dimension: Option<pivot::Dimension>,
+ coordinate: &'a Series,
+ coordinate_to_index: HashMap<usize, usize>,
}
let mut rotate_inner_column_labels = false;
.first()
.map(|child| child.variables())
.unwrap_or_default();
- let mut dimensions = Vec::new();
- let mut coordinates = Vec::new();
+ let mut dims = Vec::new();
decode_dimensions(
columns.into_iter().map(|vr| vr.reference.as_str()),
&series,
&mut rotate_outer_row_labels,
&footnotes,
1,
- &mut dimensions,
- &mut coordinates,
+ &mut dims,
);
let rows = cross
.get(1)
&mut rotate_outer_row_labels,
&footnotes,
1 + columns.len(),
- &mut dimensions,
- &mut coordinates,
+ &mut dims,
);
let mut level_ofs = columns.len() + rows.len() + 1;
&mut rotate_outer_row_labels,
&footnotes,
level_ofs,
- &mut dimensions,
- &mut coordinates,
+ &mut dims,
);
level_ofs += layers.len();
}
+ let dimensions = dims
+ .iter_mut()
+ .map(|dim| (dim.axis, dim.dimension.take().unwrap()))
+ .collect::<Vec<_>>();
+
let mut pivot_table = PivotTable::new(dimensions);
let cell = series.get("cell").unwrap()/*XXX*/;
- let mut coords = Vec::with_capacity(coordinates.len());
+ let mut coords = Vec::with_capacity(dims.len());
let (cell_formats, format_map) = graph.interval.labeling.decode_format_map(&series);
let cell_footnotes =
graph
});
for (i, cell) in cell.values.iter().enumerate() {
coords.clear();
- for series in &coordinates {
+ for dim in &dims {
// XXX indexing of values, and unwrap
- coords.push(series.values[i].category().unwrap());
+ let coordinate = dim.coordinate.values[i].category().unwrap();
+ let index = match dim.coordinate_to_index.get(&coordinate) {
+ Some(index) => *index,
+ None => panic!("can't find {coordinate}"),
+ };
+ coords.push(index);
}
let format = if let Some(cell_formats) = &cell_formats {