@cellaware/utils 8.11.20 → 8.11.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -679,8 +679,37 @@ function pivotData(data, rowGroupCols, pivotCols, valueCols) {
679
679
  }
680
680
  grouped.get(groupKey).push(row);
681
681
  }
682
- const rows = [];
682
+ const valueColumnNames = new Set();
683
683
  const mappedColumnNames = new Map();
684
+ const rows = [];
685
+ /* When processing pivoted data, we need to extract all possible value
686
+ columns first. This is to manually initialize these columns before
687
+ we start writing row values. If we do not initialize these, we will
688
+ likely end up with an incomplete result.
689
+ */
690
+ // Extract all value columns and get mapped column names.
691
+ for (const groupRows of grouped.values()) {
692
+ const pivotKeys = new Set();
693
+ for (const row of groupRows) {
694
+ pivotKeys.add(pivotBy(row));
695
+ }
696
+ for (const pivotKey of pivotKeys.values()) {
697
+ for (const { field, aggFunc } of valueCols) {
698
+ const key = `${pivotKey} ${field}`;
699
+ valueColumnNames.add(key);
700
+ let columnNames = mappedColumnNames.get(field);
701
+ if (!!columnNames) {
702
+ columnNames.add(key);
703
+ }
704
+ else {
705
+ columnNames = new Set([key]);
706
+ mappedColumnNames.set(field, columnNames);
707
+ }
708
+ }
709
+ }
710
+ }
711
+ // Build results.
712
+ const valueColumnNamesArr = Array.from(valueColumnNames);
684
713
  for (const [groupKey, groupRows] of grouped.entries()) {
685
714
  const groupObj = JSON.parse(groupKey);
686
715
  const pivotBuckets = new Map();
@@ -691,62 +720,38 @@ function pivotData(data, rowGroupCols, pivotCols, valueCols) {
691
720
  }
692
721
  pivotBuckets.get(pivotKey).push(row);
693
722
  }
723
+ // Initialize value columns first.
724
+ for (const valueColumnName of valueColumnNamesArr) {
725
+ groupObj[valueColumnName] = 0;
726
+ }
727
+ // Now write row data.
694
728
  for (const [pivotKey, rows] of pivotBuckets.entries()) {
695
729
  for (const { field, aggFunc } of valueCols) {
696
730
  const values = rows.map(r => r[field] ?? 0);
697
731
  const key = `${pivotKey} ${field}`;
698
- let columnNames = mappedColumnNames.get(field);
699
- if (!!columnNames) {
700
- columnNames.add(key);
701
- }
702
- else {
703
- columnNames = new Set([key]);
704
- mappedColumnNames.set(field, columnNames);
705
- }
706
732
  switch (aggFunc) {
707
733
  case 'sum':
708
734
  groupObj[key] = values.map(Number).reduce((a, b) => a + b, 0);
709
- if (!groupObj[key]) {
710
- groupObj[key] = 0;
711
- }
712
735
  break;
713
736
  case 'count':
714
737
  groupObj[key] = values.length;
715
- if (!groupObj[key]) {
716
- groupObj[key] = 0;
717
- }
718
738
  break;
719
739
  case 'min':
720
740
  groupObj[key] = values.reduce((a, b) => (a < b ? a : b), values[0]);
721
- if (!groupObj[key]) {
722
- groupObj[key] = 0;
723
- }
724
741
  break;
725
742
  case 'max':
726
743
  groupObj[key] = values.reduce((a, b) => (a > b ? a : b), values[0]);
727
- if (!groupObj[key]) {
728
- groupObj[key] = 0;
729
- }
730
744
  break;
731
745
  case 'avg': {
732
746
  const nums = values.map(Number).filter(n => !isNaN(n));
733
747
  groupObj[key] = nums.length ? nums.reduce((a, b) => a + b, 0) / nums.length : null;
734
- if (!groupObj[key]) {
735
- groupObj[key] = 0;
736
- }
737
748
  break;
738
749
  }
739
750
  case 'first':
740
- groupObj[key] = values[0];
741
- if (!groupObj[key]) {
742
- groupObj[key] = '';
743
- }
751
+ groupObj[key] = values[0] ?? '';
744
752
  break;
745
753
  case 'last':
746
- groupObj[key] = values[values.length - 1];
747
- if (!groupObj[key]) {
748
- groupObj[key] = '';
749
- }
754
+ groupObj[key] = values[values.length - 1] ?? '';
750
755
  break;
751
756
  default:
752
757
  groupObj[key] = '';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cellaware/utils",
3
- "version": "8.11.20",
3
+ "version": "8.11.21",
4
4
  "description": "Cellaware Utilities for Node.js",
5
5
  "author": "Cellaware Technologies",
6
6
  "type": "module",