@tidyjs/tidy 2.5.1 → 2.6.0

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.
Files changed (230) hide show
  1. package/dist/es/addRows.js.map +1 -1
  2. package/dist/es/arrange.js +9 -5
  3. package/dist/es/arrange.js.map +1 -1
  4. package/dist/es/complete.js.map +1 -1
  5. package/dist/es/count.js +6 -2
  6. package/dist/es/count.js.map +1 -1
  7. package/dist/es/debug.js +4 -2
  8. package/dist/es/debug.js.map +1 -1
  9. package/dist/es/distinct.js +3 -3
  10. package/dist/es/distinct.js.map +1 -1
  11. package/dist/es/expand.js +18 -13
  12. package/dist/es/expand.js.map +1 -1
  13. package/dist/es/fill.js +10 -3
  14. package/dist/es/fill.js.map +1 -1
  15. package/dist/es/filter.js.map +1 -1
  16. package/dist/es/fullJoin.js +23 -20
  17. package/dist/es/fullJoin.js.map +1 -1
  18. package/dist/es/groupBy.js +56 -28
  19. package/dist/es/groupBy.js.map +1 -1
  20. package/dist/es/helpers/assignGroupKeys.js +4 -4
  21. package/dist/es/helpers/assignGroupKeys.js.map +1 -1
  22. package/dist/es/helpers/groupMap.js +2 -2
  23. package/dist/es/helpers/groupMap.js.map +1 -1
  24. package/dist/es/helpers/groupTraversal.js +5 -4
  25. package/dist/es/helpers/groupTraversal.js.map +1 -1
  26. package/dist/es/helpers/identity.js.map +1 -1
  27. package/dist/es/helpers/isObject.js.map +1 -1
  28. package/dist/es/helpers/keysFromItems.js +1 -2
  29. package/dist/es/helpers/keysFromItems.js.map +1 -1
  30. package/dist/es/helpers/singleOrArray.js.map +1 -1
  31. package/dist/es/helpers/summation.js +11 -3
  32. package/dist/es/helpers/summation.js.map +1 -1
  33. package/dist/es/innerJoin.js +37 -12
  34. package/dist/es/innerJoin.js.map +1 -1
  35. package/dist/es/item/rate.js +2 -3
  36. package/dist/es/item/rate.js.map +1 -1
  37. package/dist/es/leftJoin.js +13 -8
  38. package/dist/es/leftJoin.js.map +1 -1
  39. package/dist/es/map.js.map +1 -1
  40. package/dist/es/math/math.js.map +1 -1
  41. package/dist/es/mutate.js +1 -1
  42. package/dist/es/mutate.js.map +1 -1
  43. package/dist/es/mutateWithSummary.js +1 -1
  44. package/dist/es/mutateWithSummary.js.map +1 -1
  45. package/dist/es/pivotLonger.js +31 -7
  46. package/dist/es/pivotLonger.js.map +1 -1
  47. package/dist/es/pivotWider.js +24 -19
  48. package/dist/es/pivotWider.js.map +1 -1
  49. package/dist/es/rename.js.map +1 -1
  50. package/dist/es/replaceNully.js +1 -1
  51. package/dist/es/replaceNully.js.map +1 -1
  52. package/dist/es/select.js +3 -3
  53. package/dist/es/select.js.map +1 -1
  54. package/dist/es/selectors/contains.js.map +1 -1
  55. package/dist/es/selectors/endsWith.js.map +1 -1
  56. package/dist/es/selectors/everything.js.map +1 -1
  57. package/dist/es/selectors/matches.js.map +1 -1
  58. package/dist/es/selectors/negate.js +2 -2
  59. package/dist/es/selectors/negate.js.map +1 -1
  60. package/dist/es/selectors/numRange.js.map +1 -1
  61. package/dist/es/selectors/startsWith.js.map +1 -1
  62. package/dist/es/sequences/fullSeq.js +5 -1
  63. package/dist/es/sequences/fullSeq.js.map +1 -1
  64. package/dist/es/slice.js +2 -3
  65. package/dist/es/slice.js.map +1 -1
  66. package/dist/es/summarize.js +6 -4
  67. package/dist/es/summarize.js.map +1 -1
  68. package/dist/es/summary/deviation.js.map +1 -1
  69. package/dist/es/summary/first.js.map +1 -1
  70. package/dist/es/summary/last.js.map +1 -1
  71. package/dist/es/summary/max.js.map +1 -1
  72. package/dist/es/summary/mean.js.map +1 -1
  73. package/dist/es/summary/meanRate.js.map +1 -1
  74. package/dist/es/summary/median.js.map +1 -1
  75. package/dist/es/summary/min.js.map +1 -1
  76. package/dist/es/summary/n.js.map +1 -1
  77. package/dist/es/summary/nDistinct.js +2 -2
  78. package/dist/es/summary/nDistinct.js.map +1 -1
  79. package/dist/es/summary/sum.js.map +1 -1
  80. package/dist/es/summary/variance.js.map +1 -1
  81. package/dist/es/tally.js +4 -2
  82. package/dist/es/tally.js.map +1 -1
  83. package/dist/es/tidy.js.map +1 -1
  84. package/dist/es/total.js.map +1 -1
  85. package/dist/es/transmute.js.map +1 -1
  86. package/dist/es/vector/cumsum.js.map +1 -1
  87. package/dist/es/vector/lag.js +1 -1
  88. package/dist/es/vector/lag.js.map +1 -1
  89. package/dist/es/vector/lead.js +1 -1
  90. package/dist/es/vector/lead.js.map +1 -1
  91. package/dist/es/vector/roll.js +1 -1
  92. package/dist/es/vector/roll.js.map +1 -1
  93. package/dist/es/vector/rowNumber.js.map +1 -1
  94. package/dist/es/when.js +1 -2
  95. package/dist/es/when.js.map +1 -1
  96. package/dist/lib/addRows.js +0 -2
  97. package/dist/lib/addRows.js.map +1 -1
  98. package/dist/lib/arrange.js +9 -7
  99. package/dist/lib/arrange.js.map +1 -1
  100. package/dist/lib/complete.js +0 -2
  101. package/dist/lib/complete.js.map +1 -1
  102. package/dist/lib/count.js +6 -4
  103. package/dist/lib/count.js.map +1 -1
  104. package/dist/lib/debug.js +4 -4
  105. package/dist/lib/debug.js.map +1 -1
  106. package/dist/lib/distinct.js +3 -5
  107. package/dist/lib/distinct.js.map +1 -1
  108. package/dist/lib/expand.js +18 -15
  109. package/dist/lib/expand.js.map +1 -1
  110. package/dist/lib/fill.js +10 -5
  111. package/dist/lib/fill.js.map +1 -1
  112. package/dist/lib/filter.js +0 -2
  113. package/dist/lib/filter.js.map +1 -1
  114. package/dist/lib/fullJoin.js +22 -21
  115. package/dist/lib/fullJoin.js.map +1 -1
  116. package/dist/lib/groupBy.js +56 -30
  117. package/dist/lib/groupBy.js.map +1 -1
  118. package/dist/lib/helpers/assignGroupKeys.js +4 -6
  119. package/dist/lib/helpers/assignGroupKeys.js.map +1 -1
  120. package/dist/lib/helpers/groupMap.js +2 -4
  121. package/dist/lib/helpers/groupMap.js.map +1 -1
  122. package/dist/lib/helpers/groupTraversal.js +5 -6
  123. package/dist/lib/helpers/groupTraversal.js.map +1 -1
  124. package/dist/lib/helpers/identity.js +0 -2
  125. package/dist/lib/helpers/identity.js.map +1 -1
  126. package/dist/lib/helpers/isObject.js +0 -2
  127. package/dist/lib/helpers/isObject.js.map +1 -1
  128. package/dist/lib/helpers/keysFromItems.js +1 -4
  129. package/dist/lib/helpers/keysFromItems.js.map +1 -1
  130. package/dist/lib/helpers/singleOrArray.js +0 -2
  131. package/dist/lib/helpers/singleOrArray.js.map +1 -1
  132. package/dist/lib/helpers/summation.js +10 -4
  133. package/dist/lib/helpers/summation.js.map +1 -1
  134. package/dist/lib/index.js +0 -2
  135. package/dist/lib/index.js.map +1 -1
  136. package/dist/lib/innerJoin.js +38 -14
  137. package/dist/lib/innerJoin.js.map +1 -1
  138. package/dist/lib/item/rate.js +2 -5
  139. package/dist/lib/item/rate.js.map +1 -1
  140. package/dist/lib/leftJoin.js +12 -9
  141. package/dist/lib/leftJoin.js.map +1 -1
  142. package/dist/lib/map.js +0 -2
  143. package/dist/lib/map.js.map +1 -1
  144. package/dist/lib/math/math.js +0 -2
  145. package/dist/lib/math/math.js.map +1 -1
  146. package/dist/lib/mutate.js +1 -3
  147. package/dist/lib/mutate.js.map +1 -1
  148. package/dist/lib/mutateWithSummary.js +1 -3
  149. package/dist/lib/mutateWithSummary.js.map +1 -1
  150. package/dist/lib/pivotLonger.js +31 -9
  151. package/dist/lib/pivotLonger.js.map +1 -1
  152. package/dist/lib/pivotWider.js +24 -21
  153. package/dist/lib/pivotWider.js.map +1 -1
  154. package/dist/lib/rename.js +0 -2
  155. package/dist/lib/rename.js.map +1 -1
  156. package/dist/lib/replaceNully.js +1 -3
  157. package/dist/lib/replaceNully.js.map +1 -1
  158. package/dist/lib/select.js +3 -5
  159. package/dist/lib/select.js.map +1 -1
  160. package/dist/lib/selectors/contains.js +0 -2
  161. package/dist/lib/selectors/contains.js.map +1 -1
  162. package/dist/lib/selectors/endsWith.js +0 -2
  163. package/dist/lib/selectors/endsWith.js.map +1 -1
  164. package/dist/lib/selectors/everything.js +0 -2
  165. package/dist/lib/selectors/everything.js.map +1 -1
  166. package/dist/lib/selectors/matches.js +0 -2
  167. package/dist/lib/selectors/matches.js.map +1 -1
  168. package/dist/lib/selectors/negate.js +2 -4
  169. package/dist/lib/selectors/negate.js.map +1 -1
  170. package/dist/lib/selectors/numRange.js +0 -2
  171. package/dist/lib/selectors/numRange.js.map +1 -1
  172. package/dist/lib/selectors/startsWith.js +0 -2
  173. package/dist/lib/selectors/startsWith.js.map +1 -1
  174. package/dist/lib/sequences/fullSeq.js +5 -3
  175. package/dist/lib/sequences/fullSeq.js.map +1 -1
  176. package/dist/lib/slice.js +2 -5
  177. package/dist/lib/slice.js.map +1 -1
  178. package/dist/lib/summarize.js +6 -6
  179. package/dist/lib/summarize.js.map +1 -1
  180. package/dist/lib/summary/deviation.js +0 -2
  181. package/dist/lib/summary/deviation.js.map +1 -1
  182. package/dist/lib/summary/first.js +0 -2
  183. package/dist/lib/summary/first.js.map +1 -1
  184. package/dist/lib/summary/last.js +0 -2
  185. package/dist/lib/summary/last.js.map +1 -1
  186. package/dist/lib/summary/max.js +0 -2
  187. package/dist/lib/summary/max.js.map +1 -1
  188. package/dist/lib/summary/mean.js +0 -2
  189. package/dist/lib/summary/mean.js.map +1 -1
  190. package/dist/lib/summary/meanRate.js +0 -2
  191. package/dist/lib/summary/meanRate.js.map +1 -1
  192. package/dist/lib/summary/median.js +0 -2
  193. package/dist/lib/summary/median.js.map +1 -1
  194. package/dist/lib/summary/min.js +0 -2
  195. package/dist/lib/summary/min.js.map +1 -1
  196. package/dist/lib/summary/n.js +0 -2
  197. package/dist/lib/summary/n.js.map +1 -1
  198. package/dist/lib/summary/nDistinct.js +2 -4
  199. package/dist/lib/summary/nDistinct.js.map +1 -1
  200. package/dist/lib/summary/sum.js +0 -2
  201. package/dist/lib/summary/sum.js.map +1 -1
  202. package/dist/lib/summary/variance.js +0 -2
  203. package/dist/lib/summary/variance.js.map +1 -1
  204. package/dist/lib/tally.js +4 -4
  205. package/dist/lib/tally.js.map +1 -1
  206. package/dist/lib/tidy.js +0 -2
  207. package/dist/lib/tidy.js.map +1 -1
  208. package/dist/lib/total.js +0 -2
  209. package/dist/lib/total.js.map +1 -1
  210. package/dist/lib/transmute.js +0 -2
  211. package/dist/lib/transmute.js.map +1 -1
  212. package/dist/lib/vector/cumsum.js +0 -2
  213. package/dist/lib/vector/cumsum.js.map +1 -1
  214. package/dist/lib/vector/lag.js +1 -3
  215. package/dist/lib/vector/lag.js.map +1 -1
  216. package/dist/lib/vector/lead.js +1 -3
  217. package/dist/lib/vector/lead.js.map +1 -1
  218. package/dist/lib/vector/roll.js +1 -3
  219. package/dist/lib/vector/roll.js.map +1 -1
  220. package/dist/lib/vector/rowNumber.js +0 -2
  221. package/dist/lib/vector/rowNumber.js.map +1 -1
  222. package/dist/lib/when.js +1 -4
  223. package/dist/lib/when.js.map +1 -1
  224. package/dist/tidy.d.ts +217 -1775
  225. package/dist/umd/tidy.js +307 -184
  226. package/dist/umd/tidy.js.map +1 -1
  227. package/dist/umd/tidy.min.js +1 -1
  228. package/dist/umd/tidy.min.js.map +1 -1
  229. package/package.json +14 -9
  230. package/LICENSE +0 -21
@@ -1 +1 @@
1
- {"version":3,"file":"addRows.js","sources":["../../src/addRows.ts"],"sourcesContent":["import { SingleOrArray, singleOrArray } from './helpers/singleOrArray';\nimport { TidyFn } from './types';\n\n/**\n * adds items to the end of the collection\n * @param itemsToAdd The rows/items to be appended to end of collection\n */\nexport function addRows<T extends object>(\n itemsToAdd: SingleOrArray<T> | ((items: T[]) => SingleOrArray<T>)\n): TidyFn<T> {\n const _addRows: TidyFn<T> = (items: T[]): T[] => {\n // TODO: allow options for specifying where it is inserted?\n if (typeof itemsToAdd === 'function') {\n return [...items, ...singleOrArray((itemsToAdd as Function)(items))];\n }\n\n return [...items, ...singleOrArray(itemsToAdd)];\n };\n\n return _addRows;\n}\n"],"names":[],"mappings":";;iBAQE;AAEA,QAAM,WAAsB,CAAC;AAE3B,QAAI,OAAO,eAAe;AACxB,aAAO,CAAC,GAAG,OAAO,GAAG,cAAe,WAAwB;AAAA;AAG9D,WAAO,CAAC,GAAG,OAAO,GAAG,cAAc;AAAA;AAGrC,SAAO;AAAA;;;;"}
1
+ {"version":3,"file":"addRows.js","sources":["../../src/addRows.ts"],"sourcesContent":["import { SingleOrArray, singleOrArray } from './helpers/singleOrArray';\nimport { TidyFn } from './types';\n\n/**\n * adds items to the end of the collection\n * @param itemsToAdd The rows/items to be appended to end of collection\n */\nexport function addRows<T extends object>(\n itemsToAdd: SingleOrArray<T> | ((items: T[]) => SingleOrArray<T>)\n): TidyFn<T> {\n const _addRows: TidyFn<T> = (items: T[]): T[] => {\n // TODO: allow options for specifying where it is inserted?\n if (typeof itemsToAdd === 'function') {\n return [...items, ...singleOrArray((itemsToAdd as Function)(items))];\n }\n\n return [...items, ...singleOrArray(itemsToAdd)];\n };\n\n return _addRows;\n}\n"],"names":[],"mappings":";;AAOO,SAAS,QACd,UACW,EAAA;AACX,EAAM,MAAA,QAAA,GAAsB,CAAC,KAAoB,KAAA;AAE/C,IAAI,IAAA,OAAO,eAAe,UAAY,EAAA;AACpC,MAAO,OAAA,CAAC,GAAG,KAAO,EAAA,GAAG,cAAe,UAAwB,CAAA,KAAK,CAAC,CAAC,CAAA,CAAA;AAAA,KACrE;AAEA,IAAA,OAAO,CAAC,GAAG,KAAA,EAAO,GAAG,aAAA,CAAc,UAAU,CAAC,CAAA,CAAA;AAAA,GAChD,CAAA;AAEA,EAAO,OAAA,QAAA,CAAA;AACT;;;;"}
@@ -3,12 +3,16 @@ import { singleOrArray } from './helpers/singleOrArray.js';
3
3
 
4
4
  function arrange(comparators) {
5
5
  const _arrange = (items) => {
6
- const comparatorFns = singleOrArray(comparators).map((comp) => typeof comp === "function" ? comp.length === 1 ? asc(comp) : comp : asc(comp));
6
+ const comparatorFns = singleOrArray(comparators).map(
7
+ (comp) => typeof comp === "function" ? (
8
+ // length === 1 means it is an accessor (1 argument). convert to comparator via asc
9
+ comp.length === 1 ? asc(comp) : comp
10
+ ) : asc(comp)
11
+ );
7
12
  return items.slice().sort((a, b) => {
8
13
  for (const comparator of comparatorFns) {
9
14
  const result = comparator(a, b);
10
- if (result)
11
- return result;
15
+ if (result) return result;
12
16
  }
13
17
  return 0;
14
18
  });
@@ -28,9 +32,9 @@ function desc(key) {
28
32
  };
29
33
  }
30
34
  function fixedOrder(key, order, options) {
31
- let {position = "start"} = options != null ? options : {};
35
+ let { position = "start" } = options != null ? options : {};
32
36
  const positionFactor = position === "end" ? -1 : 1;
33
- const indexMap = new Map();
37
+ const indexMap = /* @__PURE__ */ new Map();
34
38
  for (let i = 0; i < order.length; ++i) {
35
39
  indexMap.set(order[i], i);
36
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"arrange.js","sources":["../../src/arrange.ts"],"sourcesContent":["import { ascending } from 'd3-array';\nimport { SingleOrArray, singleOrArray } from './helpers/singleOrArray';\nimport { Comparator, Key, KeyOrFn, TidyFn } from './types';\n\n/**\n * Sorts items\n * @param comparators Given a, b return -1 if a comes before b, 0 if equal, 1 if after\n */\nexport function arrange<T extends object>(\n // note: had to switch to returning `any` instead of using Comparator<T> (returns number)\n // for #49 - otherwise typescript failed to do type inference on accessors\n comparators: SingleOrArray<Key | ((a: T, b: T) => any)>\n): TidyFn<T> {\n const _arrange: TidyFn<T> = (items: T[]): T[] => {\n // expand strings `key` to `asc(key)`\n const comparatorFns = singleOrArray(comparators).map((comp) =>\n typeof comp === 'function'\n ? // length === 1 means it is an accessor (1 argument). convert to comparator via asc\n comp.length === 1\n ? asc(comp as (d: T) => unknown)\n : (comp as Comparator<T>)\n : asc<T>(comp)\n );\n\n return items.slice().sort((a, b) => {\n for (const comparator of comparatorFns) {\n const result = comparator(a, b);\n if (result) return result;\n }\n\n return 0;\n });\n };\n\n return _arrange;\n}\n\n/**\n * Creates an ascending comparator based on a key\n * @param key property key of T\n */\nexport function asc<T>(key: Key | ((d: T) => any)): Comparator<T> {\n const keyFn = typeof key === 'function' ? key : (d: any) => d[key];\n\n return function _asc(a: T, b: T) {\n return emptyAwareComparator(keyFn(a), keyFn(b), false);\n };\n}\n\n/**\n * Creates a descending comparator based on a key\n * @param key property key of T\n */\nexport function desc<T>(key: Key | ((d: T) => any)): Comparator<T> {\n const keyFn = typeof key === 'function' ? key : (d: any) => d[key];\n return function _desc(a: T, b: T) {\n return emptyAwareComparator(keyFn(a), keyFn(b), true);\n };\n}\n\n/**\n * Creates a comparator that sorts values based on a key\n * and a supplied array of the desired order for the values.\n * Items not found in the array will be sorted last.\n * @param order array of desired sort order\n */\nexport function fixedOrder<T>(\n key: KeyOrFn<T>,\n order: Array<T[keyof T]>,\n options?: { position?: 'start' | 'end' }\n): (a: T, b: T) => number {\n let { position = 'start' } = options ?? {};\n const positionFactor = position === 'end' ? -1 : 1;\n\n const indexMap = new Map();\n for (let i = 0; i < order.length; ++i) {\n indexMap.set(order[i], i);\n }\n\n const keyFn =\n typeof key === 'function'\n ? key\n : (d: T) => (d[key as keyof T] as unknown) as any;\n\n return function _fixedOrder(a: T, b: T) {\n const aIndex: number = indexMap.get(keyFn(a)) ?? -1;\n const bIndex: number = indexMap.get(keyFn(b)) ?? -1;\n\n if (aIndex >= 0 && bIndex >= 0) {\n return aIndex - bIndex;\n }\n\n if (aIndex >= 0) {\n return positionFactor * -1;\n }\n\n if (bIndex >= 0) {\n return positionFactor * 1;\n }\n\n return 0;\n };\n}\n\nfunction emptyAwareComparator(aInput: any, bInput: any, desc: boolean) {\n // we swap order to get descending behavior\n let a = desc ? bInput : aInput;\n let b = desc ? aInput : bInput;\n\n // NaN, null, undefined is the order for emptys\n if (isEmpty(a) && isEmpty(b)) {\n const rankA = a !== a ? 0 : a === null ? 1 : 2;\n const rankB = b !== b ? 0 : b === null ? 1 : 2;\n const order = rankA - rankB;\n return desc ? -order : order;\n }\n\n // keep empty values at the bottom\n if (isEmpty(a)) {\n return desc ? -1 : 1;\n }\n if (isEmpty(b)) {\n return desc ? 1 : -1;\n }\n\n // descending is handled by swapping the a and b args at the start\n return ascending(a, b);\n}\n\nfunction isEmpty(value: any) {\n return value == null || value !== value /* NaN check */;\n}\n"],"names":[],"mappings":";;;iBAWE;AAEA,QAAM,WAAsB,CAAC;AAE3B,UAAM,gBAAgB,cAAc,aAAa,IAAI,CAAC,SACpD,OAAO,SAAS,aAEZ,KAAK,WAAW,IACd,IAAI,QACH,OACH,IAAO;AAGb,WAAO,MAAM,QAAQ,KAAK,CAAC,GAAG;AAC5B,iBAAW,cAAc;AACvB,cAAM,SAAS,WAAW,GAAG;AAC7B,YAAI;AAAQ,iBAAO;AAAA;AAGrB,aAAO;AAAA;AAAA;AAIX,SAAO;AAAA;aAOc;AACrB,QAAM,QAAQ,OAAO,QAAQ,aAAa,MAAM,CAAC,MAAW,EAAE;AAE9D,SAAO,cAAc,GAAM;AACzB,WAAO,qBAAqB,MAAM,IAAI,MAAM,IAAI;AAAA;AAAA;cAQ5B;AACtB,QAAM,QAAQ,OAAO,QAAQ,aAAa,MAAM,CAAC,MAAW,EAAE;AAC9D,SAAO,eAAe,GAAM;AAC1B,WAAO,qBAAqB,MAAM,IAAI,MAAM,IAAI;AAAA;AAAA;oBAWlD,KACA,OACA;AAEA,MAAI,CAAE,WAAW,WAAY,4BAAW;AACxC,QAAM,iBAAiB,aAAa,QAAQ,KAAK;AAEjD,QAAM,WAAW,IAAI;AACrB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,EAAE;AAClC,aAAS,IAAI,MAAM,IAAI;AAAA;AAGzB,QAAM,QACJ,OAAO,QAAQ,aACX,MACA,CAAC,MAAU,EAAE;AAEnB,SAAO,qBAAqB,GAAM;AApFpC;AAqFI,UAAM,SAAiB,eAAS,IAAI,MAAM,QAAnB,YAA0B;AACjD,UAAM,SAAiB,eAAS,IAAI,MAAM,QAAnB,YAA0B;AAEjD,QAAI,UAAU,KAAK,UAAU;AAC3B,aAAO,SAAS;AAAA;AAGlB,QAAI,UAAU;AACZ,aAAO,iBAAiB;AAAA;AAG1B,QAAI,UAAU;AACZ,aAAO,iBAAiB;AAAA;AAG1B,WAAO;AAAA;AAAA;AAIX,8BAA8B,QAAa,QAAa;AAEtD,MAAI,IAAI,QAAO,SAAS;AACxB,MAAI,IAAI,QAAO,SAAS;AAGxB,MAAI,QAAQ,MAAM,QAAQ;AACxB,UAAM,QAAQ,MAAM,IAAI,IAAI,MAAM,OAAO,IAAI;AAC7C,UAAM,QAAQ,MAAM,IAAI,IAAI,MAAM,OAAO,IAAI;AAC7C,UAAM,QAAQ,QAAQ;AACtB,WAAO,QAAO,CAAC,QAAQ;AAAA;AAIzB,MAAI,QAAQ;AACV,WAAO,QAAO,KAAK;AAAA;AAErB,MAAI,QAAQ;AACV,WAAO,QAAO,IAAI;AAAA;AAIpB,SAAO,UAAU,GAAG;AAAA;AAGtB,iBAAiB;AACf,SAAO,SAAS,QAAQ,UAAU;AAAA;;;;"}
1
+ {"version":3,"file":"arrange.js","sources":["../../src/arrange.ts"],"sourcesContent":["import { ascending } from 'd3-array';\nimport { SingleOrArray, singleOrArray } from './helpers/singleOrArray';\nimport { Comparator, Key, KeyOrFn, TidyFn } from './types';\n\n/**\n * Sorts items\n * @param comparators Given a, b return -1 if a comes before b, 0 if equal, 1 if after\n */\nexport function arrange<T extends object>(\n // note: had to switch to returning `any` instead of using Comparator<T> (returns number)\n // for #49 - otherwise typescript failed to do type inference on accessors\n comparators: SingleOrArray<Key | ((a: T, b: T) => any)>\n): TidyFn<T> {\n const _arrange: TidyFn<T> = (items: T[]): T[] => {\n // expand strings `key` to `asc(key)`\n const comparatorFns = singleOrArray(comparators).map((comp) =>\n typeof comp === 'function'\n ? // length === 1 means it is an accessor (1 argument). convert to comparator via asc\n comp.length === 1\n ? asc(comp as (d: T) => unknown)\n : (comp as Comparator<T>)\n : asc<T>(comp)\n );\n\n return items.slice().sort((a, b) => {\n for (const comparator of comparatorFns) {\n const result = comparator(a, b);\n if (result) return result;\n }\n\n return 0;\n });\n };\n\n return _arrange;\n}\n\n/**\n * Creates an ascending comparator based on a key\n * @param key property key of T\n */\nexport function asc<T>(key: Key | ((d: T) => any)): Comparator<T> {\n const keyFn = typeof key === 'function' ? key : (d: any) => d[key];\n\n return function _asc(a: T, b: T) {\n return emptyAwareComparator(keyFn(a), keyFn(b), false);\n };\n}\n\n/**\n * Creates a descending comparator based on a key\n * @param key property key of T\n */\nexport function desc<T>(key: Key | ((d: T) => any)): Comparator<T> {\n const keyFn = typeof key === 'function' ? key : (d: any) => d[key];\n return function _desc(a: T, b: T) {\n return emptyAwareComparator(keyFn(a), keyFn(b), true);\n };\n}\n\n/**\n * Creates a comparator that sorts values based on a key\n * and a supplied array of the desired order for the values.\n * Items not found in the array will be sorted last.\n * @param order array of desired sort order\n */\nexport function fixedOrder<T>(\n key: KeyOrFn<T>,\n order: Array<T[keyof T]>,\n options?: { position?: 'start' | 'end' }\n): (a: T, b: T) => number {\n let { position = 'start' } = options ?? {};\n const positionFactor = position === 'end' ? -1 : 1;\n\n const indexMap = new Map();\n for (let i = 0; i < order.length; ++i) {\n indexMap.set(order[i], i);\n }\n\n const keyFn =\n typeof key === 'function'\n ? key\n : (d: T) => d[key as keyof T] as unknown as any;\n\n return function _fixedOrder(a: T, b: T) {\n const aIndex: number = indexMap.get(keyFn(a)) ?? -1;\n const bIndex: number = indexMap.get(keyFn(b)) ?? -1;\n\n if (aIndex >= 0 && bIndex >= 0) {\n return aIndex - bIndex;\n }\n\n if (aIndex >= 0) {\n return positionFactor * -1;\n }\n\n if (bIndex >= 0) {\n return positionFactor * 1;\n }\n\n return 0;\n };\n}\n\nfunction emptyAwareComparator(aInput: any, bInput: any, desc: boolean) {\n // we swap order to get descending behavior\n let a = desc ? bInput : aInput;\n let b = desc ? aInput : bInput;\n\n // NaN, null, undefined is the order for emptys\n if (isEmpty(a) && isEmpty(b)) {\n const rankA = a !== a ? 0 : a === null ? 1 : 2;\n const rankB = b !== b ? 0 : b === null ? 1 : 2;\n const order = rankA - rankB;\n return desc ? -order : order;\n }\n\n // keep empty values at the bottom\n if (isEmpty(a)) {\n return desc ? -1 : 1;\n }\n if (isEmpty(b)) {\n return desc ? 1 : -1;\n }\n\n // descending is handled by swapping the a and b args at the start\n return ascending(a, b);\n}\n\nfunction isEmpty(value: any) {\n return value == null || value !== value /* NaN check */;\n}\n"],"names":["desc"],"mappings":";;;AAQO,SAAS,QAGd,WACW,EAAA;AACX,EAAM,MAAA,QAAA,GAAsB,CAAC,KAAoB,KAAA;AAE/C,IAAM,MAAA,aAAA,GAAgB,aAAc,CAAA,WAAW,CAAE,CAAA,GAAA;AAAA,MAAI,CAAC,IACpD,KAAA,OAAO,IAAS,KAAA,UAAA;AAAA;AAAA,QAEZ,IAAK,CAAA,MAAA,KAAW,CACd,GAAA,GAAA,CAAI,IAAyB,CAC5B,GAAA,IAAA;AAAA,UACH,IAAO,IAAI,CAAA;AAAA,KACjB,CAAA;AAEA,IAAA,OAAO,MAAM,KAAM,EAAA,CAAE,IAAK,CAAA,CAAC,GAAG,CAAM,KAAA;AAClC,MAAA,KAAA,MAAW,cAAc,aAAe,EAAA;AACtC,QAAM,MAAA,MAAA,GAAS,UAAW,CAAA,CAAA,EAAG,CAAC,CAAA,CAAA;AAC9B,QAAA,IAAI,QAAe,OAAA,MAAA,CAAA;AAAA,OACrB;AAEA,MAAO,OAAA,CAAA,CAAA;AAAA,KACR,CAAA,CAAA;AAAA,GACH,CAAA;AAEA,EAAO,OAAA,QAAA,CAAA;AACT,CAAA;AAMO,SAAS,IAAO,GAA2C,EAAA;AAChE,EAAM,MAAA,KAAA,GAAQ,OAAO,GAAQ,KAAA,UAAA,GAAa,MAAM,CAAC,CAAA,KAAW,EAAE,GAAG,CAAA,CAAA;AAEjE,EAAO,OAAA,SAAS,IAAK,CAAA,CAAA,EAAM,CAAM,EAAA;AAC/B,IAAA,OAAO,qBAAqB,KAAM,CAAA,CAAC,GAAG,KAAM,CAAA,CAAC,GAAG,KAAK,CAAA,CAAA;AAAA,GACvD,CAAA;AACF,CAAA;AAMO,SAAS,KAAQ,GAA2C,EAAA;AACjE,EAAM,MAAA,KAAA,GAAQ,OAAO,GAAQ,KAAA,UAAA,GAAa,MAAM,CAAC,CAAA,KAAW,EAAE,GAAG,CAAA,CAAA;AACjE,EAAO,OAAA,SAAS,KAAM,CAAA,CAAA,EAAM,CAAM,EAAA;AAChC,IAAA,OAAO,qBAAqB,KAAM,CAAA,CAAC,GAAG,KAAM,CAAA,CAAC,GAAG,IAAI,CAAA,CAAA;AAAA,GACtD,CAAA;AACF,CAAA;AAQgB,SAAA,UAAA,CACd,GACA,EAAA,KAAA,EACA,OACwB,EAAA;AACxB,EAAA,IAAI,EAAE,QAAA,GAAW,OAAQ,EAAA,GAAI,4BAAW,EAAC,CAAA;AACzC,EAAM,MAAA,cAAA,GAAiB,QAAa,KAAA,KAAA,GAAQ,CAAK,CAAA,GAAA,CAAA,CAAA;AAEjD,EAAM,MAAA,QAAA,uBAAe,GAAI,EAAA,CAAA;AACzB,EAAA,KAAA,IAAS,IAAI,CAAG,EAAA,CAAA,GAAI,KAAM,CAAA,MAAA,EAAQ,EAAE,CAAG,EAAA;AACrC,IAAA,QAAA,CAAS,GAAI,CAAA,KAAA,CAAM,CAAC,CAAA,EAAG,CAAC,CAAA,CAAA;AAAA,GAC1B;AAEA,EAAM,MAAA,KAAA,GACJ,OAAO,GAAQ,KAAA,UAAA,GACX,MACA,CAAC,CAAA,KAAS,EAAE,GAAc,CAAA,CAAA;AAEhC,EAAO,OAAA,SAAS,WAAY,CAAA,CAAA,EAAM,CAAM,EAAA;AApF1C,IAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAqFI,IAAA,MAAM,UAAiB,EAAS,GAAA,QAAA,CAAA,GAAA,CAAI,MAAM,CAAC,CAAC,MAArB,IAA0B,GAAA,EAAA,GAAA,CAAA,CAAA,CAAA;AACjD,IAAA,MAAM,UAAiB,EAAS,GAAA,QAAA,CAAA,GAAA,CAAI,MAAM,CAAC,CAAC,MAArB,IAA0B,GAAA,EAAA,GAAA,CAAA,CAAA,CAAA;AAEjD,IAAI,IAAA,MAAA,IAAU,CAAK,IAAA,MAAA,IAAU,CAAG,EAAA;AAC9B,MAAA,OAAO,MAAS,GAAA,MAAA,CAAA;AAAA,KAClB;AAEA,IAAA,IAAI,UAAU,CAAG,EAAA;AACf,MAAA,OAAO,cAAiB,GAAA,CAAA,CAAA,CAAA;AAAA,KAC1B;AAEA,IAAA,IAAI,UAAU,CAAG,EAAA;AACf,MAAA,OAAO,cAAiB,GAAA,CAAA,CAAA;AAAA,KAC1B;AAEA,IAAO,OAAA,CAAA,CAAA;AAAA,GACT,CAAA;AACF,CAAA;AAEA,SAAS,oBAAA,CAAqB,MAAa,EAAA,MAAA,EAAaA,KAAe,EAAA;AAErE,EAAI,IAAA,CAAA,GAAIA,QAAO,MAAS,GAAA,MAAA,CAAA;AACxB,EAAI,IAAA,CAAA,GAAIA,QAAO,MAAS,GAAA,MAAA,CAAA;AAGxB,EAAA,IAAI,OAAQ,CAAA,CAAC,CAAK,IAAA,OAAA,CAAQ,CAAC,CAAG,EAAA;AAC5B,IAAA,MAAM,QAAQ,CAAM,KAAA,CAAA,GAAI,CAAI,GAAA,CAAA,KAAM,OAAO,CAAI,GAAA,CAAA,CAAA;AAC7C,IAAA,MAAM,QAAQ,CAAM,KAAA,CAAA,GAAI,CAAI,GAAA,CAAA,KAAM,OAAO,CAAI,GAAA,CAAA,CAAA;AAC7C,IAAA,MAAM,QAAQ,KAAQ,GAAA,KAAA,CAAA;AACtB,IAAOA,OAAAA,KAAAA,GAAO,CAAC,KAAQ,GAAA,KAAA,CAAA;AAAA,GACzB;AAGA,EAAI,IAAA,OAAA,CAAQ,CAAC,CAAG,EAAA;AACd,IAAA,OAAOA,QAAO,CAAK,CAAA,GAAA,CAAA,CAAA;AAAA,GACrB;AACA,EAAI,IAAA,OAAA,CAAQ,CAAC,CAAG,EAAA;AACd,IAAA,OAAOA,QAAO,CAAI,GAAA,CAAA,CAAA,CAAA;AAAA,GACpB;AAGA,EAAO,OAAA,SAAA,CAAU,GAAG,CAAC,CAAA,CAAA;AACvB,CAAA;AAEA,SAAS,QAAQ,KAAY,EAAA;AAC3B,EAAO,OAAA,KAAA,IAAS,QAAQ,KAAU,KAAA,KAAA,CAAA;AACpC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"complete.js","sources":["../../src/complete.ts"],"sourcesContent":["import { expand, KeyMap } from './expand';\nimport { leftJoin } from './leftJoin';\nimport { Key, TidyFn } from './types';\nimport { replaceNully } from './replaceNully';\nimport { SingleOrArray } from './helpers/singleOrArray';\n\n/**\n * Complete a collection with missing combinations of data\n * @param expandKeys The keys to expand to all combinations of\n * @param replaceNullySpec a map from key name to value of how to deal with undefined values\n */\nexport function complete<T extends object>(\n expandKeys: SingleOrArray<Key> | KeyMap<T>,\n replaceNullySpec?: Partial<T> | null | undefined\n): TidyFn<T> {\n const _complete: TidyFn<T> = (items: T[]): T[] => {\n const expanded = expand<T, any>(expandKeys)(items);\n const joined = leftJoin(items)(expanded) as T[]; // actually may have some undefineds...\n return replaceNullySpec\n ? (replaceNully(replaceNullySpec)(joined) as T[])\n : joined;\n };\n\n return _complete;\n}\n"],"names":[],"mappings":";;;;kBAYE,YACA;AAEA,QAAM,YAAuB,CAAC;AAC5B,UAAM,WAAW,OAAe,YAAY;AAC5C,UAAM,SAAS,SAAS,OAAO;AAC/B,WAAO,mBACF,aAAa,kBAAkB,UAChC;AAAA;AAGN,SAAO;AAAA;;;;"}
1
+ {"version":3,"file":"complete.js","sources":["../../src/complete.ts"],"sourcesContent":["import { expand, KeyMap } from './expand';\nimport { leftJoin } from './leftJoin';\nimport { Key, TidyFn } from './types';\nimport { replaceNully } from './replaceNully';\nimport { SingleOrArray } from './helpers/singleOrArray';\n\n/**\n * Complete a collection with missing combinations of data\n * @param expandKeys The keys to expand to all combinations of\n * @param replaceNullySpec a map from key name to value of how to deal with undefined values\n */\nexport function complete<T extends object>(\n expandKeys: SingleOrArray<Key> | KeyMap<T>,\n replaceNullySpec?: Partial<T> | null | undefined\n): TidyFn<T> {\n const _complete: TidyFn<T> = (items: T[]): T[] => {\n const expanded = expand<T, any>(expandKeys)(items);\n const joined = leftJoin(items)(expanded) as T[]; // actually may have some undefineds...\n return replaceNullySpec\n ? (replaceNully(replaceNullySpec)(joined) as T[])\n : joined;\n };\n\n return _complete;\n}\n"],"names":[],"mappings":";;;;AAWgB,SAAA,QAAA,CACd,YACA,gBACW,EAAA;AACX,EAAM,MAAA,SAAA,GAAuB,CAAC,KAAoB,KAAA;AAChD,IAAA,MAAM,QAAW,GAAA,MAAA,CAAe,UAAU,CAAA,CAAE,KAAK,CAAA,CAAA;AACjD,IAAA,MAAM,MAAS,GAAA,QAAA,CAAS,KAAK,CAAA,CAAE,QAAQ,CAAA,CAAA;AACvC,IAAA,OAAO,gBACF,GAAA,YAAA,CAAa,gBAAgB,CAAA,CAAE,MAAM,CACtC,GAAA,MAAA,CAAA;AAAA,GACN,CAAA;AAEA,EAAO,OAAA,SAAA,CAAA;AACT;;;;"}
package/dist/es/count.js CHANGED
@@ -7,8 +7,12 @@ import { tidy } from './tidy.js';
7
7
  function count(groupKeys, options) {
8
8
  const _count = (items) => {
9
9
  options = options != null ? options : {};
10
- const {name = "n", sort} = options;
11
- const results = tidy(items, groupBy(groupKeys, [tally(options)]), sort ? arrange(desc(name)) : identity);
10
+ const { name = "n", sort } = options;
11
+ const results = tidy(
12
+ items,
13
+ groupBy(groupKeys, [tally(options)]),
14
+ sort ? arrange(desc(name)) : identity
15
+ );
12
16
  return results;
13
17
  };
14
18
  return _count;
@@ -1 +1 @@
1
- {"version":3,"file":"count.js","sources":["../../src/count.ts"],"sourcesContent":["import { arrange, desc } from './arrange';\nimport { groupBy } from './groupBy';\nimport { identity } from './helpers/identity';\nimport { SingleOrArray } from './helpers/singleOrArray';\nimport { tally } from './tally';\nimport { tidy } from './tidy';\nimport { KeyOrFn } from './types';\n\ntype CountOptions = {\n name?: string;\n sort?: boolean;\n wt?: string;\n};\n\n/**\n * Tallies the number distinct values for the specified keys and adds\n * the count as a new key (default `n`). Optionally sorts by the count.\n */\nexport function count<T extends object, Keys extends SingleOrArray<KeyOrFn<T>>>(\n groupKeys: Keys,\n options?: CountOptions | null | undefined\n) {\n const _count = (items: T[]) => {\n options = options ?? {};\n const { name = 'n', sort } = options;\n\n const results = tidy(\n items,\n groupBy(groupKeys, [tally(options)]),\n sort ? arrange(desc(name)) : identity\n );\n\n return results;\n };\n\n return _count;\n}\n"],"names":[],"mappings":";;;;;;eAmBE,WACA;AAEA,QAAM,SAAS,CAAC;AACd,cAAU,4BAAW;AACrB,UAAM,CAAE,OAAO,KAAK,QAAS;AAE7B,UAAM,UAAU,KACd,OACA,QAAQ,WAAW,CAAC,MAAM,YAC1B,OAAO,QAAQ,KAAK,SAAS;AAG/B,WAAO;AAAA;AAGT,SAAO;AAAA;;;;"}
1
+ {"version":3,"file":"count.js","sources":["../../src/count.ts"],"sourcesContent":["import { arrange, desc } from './arrange';\nimport { groupBy } from './groupBy';\nimport { identity } from './helpers/identity';\nimport { SingleOrArray } from './helpers/singleOrArray';\nimport { tally } from './tally';\nimport { tidy } from './tidy';\nimport { KeyOrFn } from './types';\n\ntype CountOptions = {\n name?: string;\n sort?: boolean;\n wt?: string;\n};\n\n/**\n * Tallies the number distinct values for the specified keys and adds\n * the count as a new key (default `n`). Optionally sorts by the count.\n */\nexport function count<T extends object, Keys extends SingleOrArray<KeyOrFn<T>>>(\n groupKeys: Keys,\n options?: CountOptions | null | undefined\n) {\n const _count = (items: T[]) => {\n options = options ?? {};\n const { name = 'n', sort } = options;\n\n const results = tidy(\n items,\n groupBy(groupKeys, [tally(options)]),\n sort ? arrange(desc(name)) : identity\n );\n\n return results;\n };\n\n return _count;\n}\n"],"names":[],"mappings":";;;;;;AAkBgB,SAAA,KAAA,CACd,WACA,OACA,EAAA;AACA,EAAM,MAAA,MAAA,GAAS,CAAC,KAAe,KAAA;AAC7B,IAAA,OAAA,GAAU,4BAAW,EAAC,CAAA;AACtB,IAAA,MAAM,EAAE,IAAA,GAAO,GAAK,EAAA,IAAA,EAAS,GAAA,OAAA,CAAA;AAE7B,IAAA,MAAM,OAAU,GAAA,IAAA;AAAA,MACd,KAAA;AAAA,MACA,QAAQ,SAAW,EAAA,CAAC,KAAM,CAAA,OAAO,CAAC,CAAC,CAAA;AAAA,MACnC,IAAO,GAAA,OAAA,CAAQ,IAAK,CAAA,IAAI,CAAC,CAAI,GAAA,QAAA;AAAA,KAC/B,CAAA;AAEA,IAAO,OAAA,OAAA,CAAA;AAAA,GACT,CAAA;AAEA,EAAO,OAAA,MAAA,CAAA;AACT;;;;"}
package/dist/es/debug.js CHANGED
@@ -10,13 +10,15 @@ function debug(label, options) {
10
10
  }
11
11
  }
12
12
  options = options != null ? options : {};
13
- const {limit = 10, output = "table"} = options;
13
+ const { limit = 10, output = "table" } = options;
14
14
  const dashString = "--------------------------------------------------------------------------------";
15
15
  let numDashes = dashString.length;
16
16
  const prefixedLabel = prefix + "]" + (label == null ? "" : " " + label);
17
17
  numDashes = Math.max(0, numDashes - (prefixedLabel.length + 2));
18
18
  console.log(`${prefixedLabel} ${dashString.substring(0, numDashes)}`);
19
- console[output](limit == null || limit >= items.length ? items : items.slice(0, limit));
19
+ console[output](
20
+ limit == null || limit >= items.length ? items : items.slice(0, limit)
21
+ );
20
22
  return items;
21
23
  };
22
24
  return _debug;
@@ -1 +1 @@
1
- {"version":3,"file":"debug.js","sources":["../../src/debug.ts"],"sourcesContent":["import { TidyContext, TidyFn } from './types';\n\ntype Options = {\n limit?: number | null;\n output?: 'log' | 'table';\n};\n\n/**\n * Debugs items\n */\nexport function debug<T extends object>(\n label?: string | null | undefined,\n options?: Options | null | undefined\n): TidyFn<T> {\n const _debug: TidyFn<T> = (items: T[], context?: TidyContext): T[] => {\n let prefix = '[tidy.debug';\n if (context?.groupKeys?.length) {\n const groupKeys = context.groupKeys;\n const groupKeyStrings = groupKeys\n .map((keyPair: any) => keyPair.join(': '))\n .join(', ');\n if (groupKeyStrings.length) {\n prefix += '|' + groupKeyStrings;\n }\n }\n options = options ?? {};\n const { limit = 10, output = 'table' } = options;\n\n // check for sneaky group keys as last arg\n const dashString =\n '--------------------------------------------------------------------------------';\n let numDashes = dashString.length;\n const prefixedLabel = prefix + ']' + (label == null ? '' : ' ' + label);\n numDashes = Math.max(0, numDashes - (prefixedLabel.length + 2));\n\n console.log(`${prefixedLabel} ${dashString.substring(0, numDashes)}`);\n console[output](\n limit == null || limit >= items.length ? items : items.slice(0, limit)\n );\n return items;\n };\n\n return _debug;\n}\n"],"names":[],"mappings":"eAWE,OACA;AAEA,QAAM,SAAoB,CAAC,OAAY;AAdzC;AAeI,QAAI,SAAS;AACb,QAAI,yCAAS,cAAT,mBAAoB;AACtB,YAAM,YAAY,QAAQ;AAC1B,YAAM,kBAAkB,UACrB,IAAI,CAAC,YAAiB,QAAQ,KAAK,OACnC,KAAK;AACR,UAAI,gBAAgB;AAClB,kBAAU,MAAM;AAAA;AAAA;AAGpB,cAAU,4BAAW;AACrB,UAAM,CAAE,QAAQ,IAAI,SAAS,WAAY;AAGzC,UAAM,aACJ;AACF,QAAI,YAAY,WAAW;AAC3B,UAAM,gBAAgB,SAAS,gBAAgB,OAAO,KAAK,MAAM;AACjE,gBAAY,KAAK,IAAI,GAAG,2BAA2B,SAAS;AAE5D,YAAQ,IAAI,GAAG,iBAAiB,WAAW,UAAU,GAAG;AACxD,YAAQ,QACN,SAAS,QAAQ,SAAS,MAAM,SAAS,QAAQ,MAAM,MAAM,GAAG;AAElE,WAAO;AAAA;AAGT,SAAO;AAAA;;;;"}
1
+ {"version":3,"file":"debug.js","sources":["../../src/debug.ts"],"sourcesContent":["import { TidyContext, TidyFn } from './types';\n\ntype Options = {\n limit?: number | null;\n output?: 'log' | 'table';\n};\n\n/**\n * Debugs items\n */\nexport function debug<T extends object>(\n label?: string | null | undefined,\n options?: Options | null | undefined\n): TidyFn<T> {\n const _debug: TidyFn<T> = (items: T[], context?: TidyContext): T[] => {\n let prefix = '[tidy.debug';\n if (context?.groupKeys?.length) {\n const groupKeys = context.groupKeys;\n const groupKeyStrings = groupKeys\n .map((keyPair: any) => keyPair.join(': '))\n .join(', ');\n if (groupKeyStrings.length) {\n prefix += '|' + groupKeyStrings;\n }\n }\n options = options ?? {};\n const { limit = 10, output = 'table' } = options;\n\n // check for sneaky group keys as last arg\n const dashString =\n '--------------------------------------------------------------------------------';\n let numDashes = dashString.length;\n const prefixedLabel = prefix + ']' + (label == null ? '' : ' ' + label);\n numDashes = Math.max(0, numDashes - (prefixedLabel.length + 2));\n\n console.log(`${prefixedLabel} ${dashString.substring(0, numDashes)}`);\n console[output](\n limit == null || limit >= items.length ? items : items.slice(0, limit)\n );\n return items;\n };\n\n return _debug;\n}\n"],"names":[],"mappings":"AAUgB,SAAA,KAAA,CACd,OACA,OACW,EAAA;AACX,EAAM,MAAA,MAAA,GAAoB,CAAC,KAAA,EAAY,OAA+B,KAAA;AAdxE,IAAA,IAAA,EAAA,CAAA;AAeI,IAAA,IAAI,MAAS,GAAA,aAAA,CAAA;AACb,IAAI,IAAA,CAAA,EAAA,GAAA,OAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,OAAA,CAAS,SAAT,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAoB,MAAQ,EAAA;AAC9B,MAAA,MAAM,YAAY,OAAQ,CAAA,SAAA,CAAA;AAC1B,MAAM,MAAA,eAAA,GAAkB,SACrB,CAAA,GAAA,CAAI,CAAC,OAAA,KAAiB,OAAQ,CAAA,IAAA,CAAK,IAAI,CAAC,CACxC,CAAA,IAAA,CAAK,IAAI,CAAA,CAAA;AACZ,MAAA,IAAI,gBAAgB,MAAQ,EAAA;AAC1B,QAAA,MAAA,IAAU,GAAM,GAAA,eAAA,CAAA;AAAA,OAClB;AAAA,KACF;AACA,IAAA,OAAA,GAAU,4BAAW,EAAC,CAAA;AACtB,IAAA,MAAM,EAAE,KAAA,GAAQ,EAAI,EAAA,MAAA,GAAS,SAAY,GAAA,OAAA,CAAA;AAGzC,IAAA,MAAM,UACJ,GAAA,kFAAA,CAAA;AACF,IAAA,IAAI,YAAY,UAAW,CAAA,MAAA,CAAA;AAC3B,IAAA,MAAM,gBAAgB,MAAS,GAAA,GAAA,IAAO,KAAS,IAAA,IAAA,GAAO,KAAK,GAAM,GAAA,KAAA,CAAA,CAAA;AACjE,IAAA,SAAA,GAAY,KAAK,GAAI,CAAA,CAAA,EAAG,SAAa,IAAA,aAAA,CAAc,SAAS,CAAE,CAAA,CAAA,CAAA;AAE9D,IAAQ,OAAA,CAAA,GAAA,CAAI,GAAG,aAAa,CAAA,CAAA,EAAI,WAAW,SAAU,CAAA,CAAA,EAAG,SAAS,CAAC,CAAE,CAAA,CAAA,CAAA;AACpE,IAAA,OAAA,CAAQ,MAAM,CAAA;AAAA,MACZ,KAAA,IAAS,QAAQ,KAAS,IAAA,KAAA,CAAM,SAAS,KAAQ,GAAA,KAAA,CAAM,KAAM,CAAA,CAAA,EAAG,KAAK,CAAA;AAAA,KACvE,CAAA;AACA,IAAO,OAAA,KAAA,CAAA;AAAA,GACT,CAAA;AAEA,EAAO,OAAA,MAAA,CAAA;AACT;;;;"}
@@ -4,13 +4,13 @@ function distinct(keys) {
4
4
  const _distinct = (items) => {
5
5
  keys = singleOrArray(keys);
6
6
  if (!keys.length) {
7
- const set = new Set();
7
+ const set = /* @__PURE__ */ new Set();
8
8
  for (const item of items) {
9
9
  set.add(item);
10
10
  }
11
11
  return Array.from(set);
12
12
  }
13
- const rootMap = new Map();
13
+ const rootMap = /* @__PURE__ */ new Map();
14
14
  const distinctItems = [];
15
15
  const lastKey = keys[keys.length - 1];
16
16
  for (const item of items) {
@@ -27,7 +27,7 @@ function distinct(keys) {
27
27
  break;
28
28
  }
29
29
  if (!map.has(mapItemKey)) {
30
- map.set(mapItemKey, new Map());
30
+ map.set(mapItemKey, /* @__PURE__ */ new Map());
31
31
  }
32
32
  map = map.get(mapItemKey);
33
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"distinct.js","sources":["../../src/distinct.ts"],"sourcesContent":["import { KeyOrFn, TidyFn } from './types';\nimport { SingleOrArray, singleOrArray } from './helpers/singleOrArray';\n\n/**\n * Removes items with duplicate values for the specified keys.\n * If no keys provided, uses strict equality.\n *\n * @param keys Keys to compute distinct across\n */\nexport function distinct<T extends object>(\n keys?: SingleOrArray<KeyOrFn<T>> | null | undefined\n): TidyFn<T> {\n const _distinct: TidyFn<T> = (items: T[]): T[] => {\n keys = singleOrArray(keys);\n\n if (!keys.length) {\n // https://jsperf.com/unique-array-by-strict-equality\n const set = new Set<T>();\n for (const item of items) {\n set.add(item);\n }\n return Array.from(set);\n }\n\n // compare keys\n // https://jsperf.com/distinct-by-key\n // turns out nested Maps are faster than string keys. AND they support\n // and arbitrary value.\n const rootMap = new Map();\n const distinctItems: T[] = [];\n const lastKey = keys[keys.length - 1];\n for (const item of items) {\n let map = rootMap;\n let hasItem = false;\n\n // go through each key to find out if we have it\n for (const key of keys) {\n const mapItemKey =\n typeof key === 'function' ? key(item) : item[key as keyof T];\n // last key, check if we already added it\n if (key === lastKey) {\n hasItem = map.has(mapItemKey);\n if (!hasItem) {\n distinctItems.push(item);\n map.set(mapItemKey, true);\n }\n break;\n }\n\n // create maps all the way down\n if (!map.has(mapItemKey)) {\n map.set(mapItemKey, new Map());\n }\n\n // move to next inner map\n map = map.get(mapItemKey);\n }\n }\n\n return distinctItems;\n };\n\n return _distinct;\n}\n"],"names":[],"mappings":";;kBAUE;AAEA,QAAM,YAAuB,CAAC;AAC5B,WAAO,cAAc;AAErB,QAAI,CAAC,KAAK;AAER,YAAM,MAAM,IAAI;AAChB,iBAAW,QAAQ;AACjB,YAAI,IAAI;AAAA;AAEV,aAAO,MAAM,KAAK;AAAA;AAOpB,UAAM,UAAU,IAAI;AACpB,UAAM,gBAAqB;AAC3B,UAAM,UAAU,KAAK,KAAK,SAAS;AACnC,eAAW,QAAQ;AACjB,UAAI,MAAM;AACV,UAAI,UAAU;AAGd,iBAAW,OAAO;AAChB,cAAM,aACJ,OAAO,QAAQ,aAAa,IAAI,QAAQ,KAAK;AAE/C,YAAI,QAAQ;AACV,oBAAU,IAAI,IAAI;AAClB,cAAI,CAAC;AACH,0BAAc,KAAK;AACnB,gBAAI,IAAI,YAAY;AAAA;AAEtB;AAAA;AAIF,YAAI,CAAC,IAAI,IAAI;AACX,cAAI,IAAI,YAAY,IAAI;AAAA;AAI1B,cAAM,IAAI,IAAI;AAAA;AAAA;AAIlB,WAAO;AAAA;AAGT,SAAO;AAAA;;;;"}
1
+ {"version":3,"file":"distinct.js","sources":["../../src/distinct.ts"],"sourcesContent":["import { KeyOrFn, TidyFn } from './types';\nimport { SingleOrArray, singleOrArray } from './helpers/singleOrArray';\n\n/**\n * Removes items with duplicate values for the specified keys.\n * If no keys provided, uses strict equality.\n *\n * @param keys Keys to compute distinct across\n */\nexport function distinct<T extends object>(\n keys?: SingleOrArray<KeyOrFn<T>> | null | undefined\n): TidyFn<T> {\n const _distinct: TidyFn<T> = (items: T[]): T[] => {\n keys = singleOrArray(keys);\n\n if (!keys.length) {\n // https://jsperf.com/unique-array-by-strict-equality\n const set = new Set<T>();\n for (const item of items) {\n set.add(item);\n }\n return Array.from(set);\n }\n\n // compare keys\n // https://jsperf.com/distinct-by-key\n // turns out nested Maps are faster than string keys. AND they support\n // and arbitrary value.\n const rootMap = new Map();\n const distinctItems: T[] = [];\n const lastKey = keys[keys.length - 1];\n for (const item of items) {\n let map = rootMap;\n let hasItem = false;\n\n // go through each key to find out if we have it\n for (const key of keys) {\n const mapItemKey =\n typeof key === 'function' ? key(item) : item[key as keyof T];\n // last key, check if we already added it\n if (key === lastKey) {\n hasItem = map.has(mapItemKey);\n if (!hasItem) {\n distinctItems.push(item);\n map.set(mapItemKey, true);\n }\n break;\n }\n\n // create maps all the way down\n if (!map.has(mapItemKey)) {\n map.set(mapItemKey, new Map());\n }\n\n // move to next inner map\n map = map.get(mapItemKey);\n }\n }\n\n return distinctItems;\n };\n\n return _distinct;\n}\n"],"names":[],"mappings":";;AASO,SAAS,SACd,IACW,EAAA;AACX,EAAM,MAAA,SAAA,GAAuB,CAAC,KAAoB,KAAA;AAChD,IAAA,IAAA,GAAO,cAAc,IAAI,CAAA,CAAA;AAEzB,IAAI,IAAA,CAAC,KAAK,MAAQ,EAAA;AAEhB,MAAM,MAAA,GAAA,uBAAU,GAAO,EAAA,CAAA;AACvB,MAAA,KAAA,MAAW,QAAQ,KAAO,EAAA;AACxB,QAAA,GAAA,CAAI,IAAI,IAAI,CAAA,CAAA;AAAA,OACd;AACA,MAAO,OAAA,KAAA,CAAM,KAAK,GAAG,CAAA,CAAA;AAAA,KACvB;AAMA,IAAM,MAAA,OAAA,uBAAc,GAAI,EAAA,CAAA;AACxB,IAAA,MAAM,gBAAqB,EAAC,CAAA;AAC5B,IAAA,MAAM,OAAU,GAAA,IAAA,CAAK,IAAK,CAAA,MAAA,GAAS,CAAC,CAAA,CAAA;AACpC,IAAA,KAAA,MAAW,QAAQ,KAAO,EAAA;AACxB,MAAA,IAAI,GAAM,GAAA,OAAA,CAAA;AACV,MAAA,IAAI,OAAU,GAAA,KAAA,CAAA;AAGd,MAAA,KAAA,MAAW,OAAO,IAAM,EAAA;AACtB,QAAM,MAAA,UAAA,GACJ,OAAO,GAAQ,KAAA,UAAA,GAAa,IAAI,IAAI,CAAA,GAAI,KAAK,GAAc,CAAA,CAAA;AAE7D,QAAA,IAAI,QAAQ,OAAS,EAAA;AACnB,UAAU,OAAA,GAAA,GAAA,CAAI,IAAI,UAAU,CAAA,CAAA;AAC5B,UAAA,IAAI,CAAC,OAAS,EAAA;AACZ,YAAA,aAAA,CAAc,KAAK,IAAI,CAAA,CAAA;AACvB,YAAI,GAAA,CAAA,GAAA,CAAI,YAAY,IAAI,CAAA,CAAA;AAAA,WAC1B;AACA,UAAA,MAAA;AAAA,SACF;AAGA,QAAA,IAAI,CAAC,GAAA,CAAI,GAAI,CAAA,UAAU,CAAG,EAAA;AACxB,UAAA,GAAA,CAAI,GAAI,CAAA,UAAA,kBAAgB,IAAA,GAAA,EAAK,CAAA,CAAA;AAAA,SAC/B;AAGA,QAAM,GAAA,GAAA,GAAA,CAAI,IAAI,UAAU,CAAA,CAAA;AAAA,OAC1B;AAAA,KACF;AAEA,IAAO,OAAA,aAAA,CAAA;AAAA,GACT,CAAA;AAEA,EAAO,OAAA,SAAA,CAAA;AACT;;;;"}
package/dist/es/expand.js CHANGED
@@ -12,26 +12,31 @@ function expand(expandKeys) {
12
12
  } else {
13
13
  values = Array.from(new Set(items.map((d) => d[key])));
14
14
  }
15
- vectors.push(values.map((value) => ({[key]: value})));
15
+ vectors.push(values.map((value) => ({ [key]: value })));
16
16
  }
17
17
  return makeCombinations(vectors);
18
18
  };
19
19
  return _expand;
20
20
  }
21
+ const EXPAND_WARN_THRESHOLD = 1e5;
21
22
  function makeCombinations(vectors) {
22
- function combine(accum, baseObj, remainingVectors) {
23
- if (!remainingVectors.length && baseObj != null) {
24
- accum.push(baseObj);
25
- return;
26
- }
27
- const vector = remainingVectors[0];
28
- const newRemainingArrays = remainingVectors.slice(1);
29
- for (const item of vector) {
30
- combine(accum, {...baseObj, ...item}, newRemainingArrays);
23
+ if (!vectors.length) return [];
24
+ const totalSize = vectors.reduce((acc, v) => acc * v.length, 1);
25
+ if (totalSize > EXPAND_WARN_THRESHOLD) {
26
+ console.warn(
27
+ `tidy expand: generating ${totalSize.toLocaleString()} combinations. This may be slow or use excessive memory.`
28
+ );
29
+ }
30
+ let result = [null];
31
+ for (const vector of vectors) {
32
+ const next = [];
33
+ for (const baseObj of result) {
34
+ for (const item of vector) {
35
+ next.push(baseObj == null ? item : { ...baseObj, ...item });
36
+ }
31
37
  }
38
+ result = next;
32
39
  }
33
- const result = [];
34
- combine(result, null, vectors);
35
40
  return result;
36
41
  }
37
42
  function makeKeyMap(keys) {
@@ -44,7 +49,7 @@ function makeKeyMap(keys) {
44
49
  } else if (typeof keys === "object") {
45
50
  return keys;
46
51
  }
47
- return {[keys]: keys};
52
+ return { [keys]: keys };
48
53
  }
49
54
 
50
55
  export { expand, makeKeyMap };
@@ -1 +1 @@
1
- {"version":3,"file":"expand.js","sources":["../../src/expand.ts"],"sourcesContent":["import { A, O } from 'ts-toolbelt';\nimport { SingleOrArray } from './helpers/singleOrArray';\nimport { Key, TidyFn } from './types';\n\n// helper types\nexport type KeyMap<T extends object = any> = Partial<\n {\n [key in keyof T]: keyof T | Array<T[key]> | ((items: T[]) => T[key][]);\n }\n>;\n\n/**\n * Expands a set of items to include all combinations of the specified keys.\n */\n// prettier-ignore\nexport function expand<T extends object = any, K extends keyof T = keyof T>(expandKeys: K): TidyFn<T, A.Compute<Pick<T, K>>>;\n// prettier-ignore\nexport function expand<T extends object = any, K extends (keyof T)[] = (keyof T)[]>(expandKeys: K): TidyFn<T, A.Compute<Pick<T, K[number]>>>;\n// prettier-ignore\nexport function expand<T extends object = any, K extends KeyMap<T> = KeyMap<T>>(expandKeys: K): TidyFn<T, O.Pick<T, keyof K>>\n// prettier-ignore\nexport function expand<T extends object>(expandKeys: SingleOrArray<Key> | KeyMap<T>): TidyFn<T> {\n const _expand: TidyFn<T> = (items: T[]) => {\n const keyMap = makeKeyMap(expandKeys);\n\n // for each key, get all distinct values or use the provided values\n const vectors = [];\n for (const key in keyMap) {\n const keyValue = keyMap[key];\n let values;\n if (typeof keyValue === 'function') {\n values = keyValue(items);\n } else if (Array.isArray(keyValue)) {\n values = keyValue;\n } else {\n // read distinct values from the key in the data\n values = Array.from(new Set(items.map((d) => d[key as keyof T])));\n }\n\n vectors.push(values.map((value: any) => ({ [key]: value })));\n }\n\n // make all combinations of all value sets\n return makeCombinations(vectors);\n };\n\n return _expand;\n}\n\n/*\n Recursively compute key combinations\n*/\nfunction makeCombinations(vectors: any[][]): any[] {\n function combine(accum: any[], baseObj: any, remainingVectors: any[][]) {\n if (!remainingVectors.length && baseObj != null) {\n accum.push(baseObj);\n return;\n }\n\n const vector = remainingVectors[0];\n const newRemainingArrays = remainingVectors.slice(1);\n for (const item of vector) {\n combine(accum, { ...baseObj, ...item }, newRemainingArrays);\n }\n }\n\n const result: any[] = [];\n combine(result, null, vectors);\n return result;\n}\n\n// convert by option in to a map from T key to JoinT key\nexport function makeKeyMap(keys: SingleOrArray<Key> | KeyMap): KeyMap {\n if (Array.isArray(keys)) {\n const keyMap: KeyMap = {};\n for (const key of keys) {\n keyMap[key as any] = key;\n }\n return keyMap;\n } else if (typeof keys === 'object') {\n return keys;\n }\n\n return { [keys]: keys as any } as KeyMap;\n}\n"],"names":[],"mappings":"gBAqByC;AACvC,QAAM,UAAqB,CAAC;AAC1B,UAAM,SAAS,WAAW;AAG1B,UAAM,UAAU;AAChB,eAAW,OAAO;AAChB,YAAM,WAAW,OAAO;AACxB,UAAI;AACJ,UAAI,OAAO,aAAa;AACtB,iBAAS,SAAS;AAAA,iBACT,MAAM,QAAQ;AACvB,iBAAS;AAAA;AAGT,iBAAS,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE;AAAA;AAGjD,cAAQ,KAAK,OAAO,IAAI,CAAC,aAAmB,MAAM;AAAA;AAIpD,WAAO,iBAAiB;AAAA;AAG1B,SAAO;AAAA;AAMT,0BAA0B;AACxB,mBAAiB,OAAc,SAAc;AAC3C,QAAI,CAAC,iBAAiB,UAAU,WAAW;AACzC,YAAM,KAAK;AACX;AAAA;AAGF,UAAM,SAAS,iBAAiB;AAChC,UAAM,qBAAqB,iBAAiB,MAAM;AAClD,eAAW,QAAQ;AACjB,cAAQ,OAAO,IAAK,YAAY,OAAQ;AAAA;AAAA;AAI5C,QAAM,SAAgB;AACtB,UAAQ,QAAQ,MAAM;AACtB,SAAO;AAAA;oBAIkB;AACzB,MAAI,MAAM,QAAQ;AAChB,UAAM,SAAiB;AACvB,eAAW,OAAO;AAChB,aAAO,OAAc;AAAA;AAEvB,WAAO;AAAA,aACE,OAAO,SAAS;AACzB,WAAO;AAAA;AAGT,SAAO,EAAG,OAAO;AAAA;;;;"}
1
+ {"version":3,"file":"expand.js","sources":["../../src/expand.ts"],"sourcesContent":["import { SingleOrArray } from './helpers/singleOrArray';\nimport { Key, TidyFn } from './types';\nimport { Prettify } from './type-utils';\n\n// helper types\nexport type KeyMap<T extends object = any> = Partial<{\n [key in keyof T]: keyof T | Array<T[key]> | ((items: T[]) => T[key][]);\n}>;\n\n/**\n * Expands a set of items to include all combinations of the specified keys.\n */\n// prettier-ignore\nexport function expand<T extends object = any, K extends keyof T = keyof T>(expandKeys: K): TidyFn<T, Prettify<Pick<T, K>>>;\n// prettier-ignore\nexport function expand<T extends object = any, K extends (keyof T)[] = (keyof T)[]>(expandKeys: K): TidyFn<T, Prettify<Pick<T, K[number]>>>;\n// prettier-ignore\nexport function expand<T extends object = any, K extends KeyMap<T> = KeyMap<T>>(expandKeys: K): TidyFn<T, Pick<T, Extract<keyof K, keyof T>>>\n// prettier-ignore\nexport function expand<T extends object>(expandKeys: SingleOrArray<Key> | KeyMap<T>): TidyFn<T> {\n const _expand: TidyFn<T> = (items: T[]) => {\n const keyMap = makeKeyMap(expandKeys);\n\n // for each key, get all distinct values or use the provided values\n const vectors = [];\n for (const key in keyMap) {\n const keyValue = keyMap[key];\n let values;\n if (typeof keyValue === 'function') {\n values = keyValue(items);\n } else if (Array.isArray(keyValue)) {\n values = keyValue;\n } else {\n // read distinct values from the key in the data\n values = Array.from(new Set(items.map((d) => d[key as keyof T])));\n }\n\n vectors.push(values.map((value: any) => ({ [key]: value })));\n }\n\n // make all combinations of all value sets\n return makeCombinations(vectors);\n };\n\n return _expand;\n}\n\n/*\n Recursively compute key combinations\n*/\nconst EXPAND_WARN_THRESHOLD = 100_000;\n\n/*\n Iteratively compute key combinations (avoids recursive array slicing)\n*/\nfunction makeCombinations(vectors: any[][]): any[] {\n if (!vectors.length) return [];\n\n // warn if Cartesian product will be very large\n const totalSize = vectors.reduce((acc, v) => acc * v.length, 1);\n if (totalSize > EXPAND_WARN_THRESHOLD) {\n console.warn(\n `tidy expand: generating ${totalSize.toLocaleString()} combinations. ` +\n `This may be slow or use excessive memory.`\n );\n }\n\n let result: any[] = [null];\n for (const vector of vectors) {\n const next: any[] = [];\n for (const baseObj of result) {\n for (const item of vector) {\n next.push(baseObj == null ? item : { ...baseObj, ...item });\n }\n }\n result = next;\n }\n return result;\n}\n\n// convert by option in to a map from T key to JoinT key\nexport function makeKeyMap(keys: SingleOrArray<Key> | KeyMap): KeyMap {\n if (Array.isArray(keys)) {\n const keyMap: KeyMap = {};\n for (const key of keys) {\n keyMap[key as any] = key;\n }\n return keyMap;\n } else if (typeof keys === 'object') {\n return keys;\n }\n\n return { [keys]: keys as any } as KeyMap;\n}\n"],"names":[],"mappings":"AAmBO,SAAS,OAAyB,UAAuD,EAAA;AAC9F,EAAM,MAAA,OAAA,GAAqB,CAAC,KAAe,KAAA;AACzC,IAAM,MAAA,MAAA,GAAS,WAAW,UAAU,CAAA,CAAA;AAGpC,IAAA,MAAM,UAAU,EAAC,CAAA;AACjB,IAAA,KAAA,MAAW,OAAO,MAAQ,EAAA;AACxB,MAAM,MAAA,QAAA,GAAW,OAAO,GAAG,CAAA,CAAA;AAC3B,MAAI,IAAA,MAAA,CAAA;AACJ,MAAI,IAAA,OAAO,aAAa,UAAY,EAAA;AAClC,QAAA,MAAA,GAAS,SAAS,KAAK,CAAA,CAAA;AAAA,OACd,MAAA,IAAA,KAAA,CAAM,OAAQ,CAAA,QAAQ,CAAG,EAAA;AAClC,QAAS,MAAA,GAAA,QAAA,CAAA;AAAA,OACJ,MAAA;AAEL,QAAA,MAAA,GAAS,KAAM,CAAA,IAAA,CAAK,IAAI,GAAA,CAAI,KAAM,CAAA,GAAA,CAAI,CAAC,CAAA,KAAM,CAAE,CAAA,GAAc,CAAC,CAAC,CAAC,CAAA,CAAA;AAAA,OAClE;AAEA,MAAQ,OAAA,CAAA,IAAA,CAAK,MAAO,CAAA,GAAA,CAAI,CAAC,KAAA,MAAgB,EAAE,CAAC,GAAG,GAAG,KAAM,EAAA,CAAE,CAAC,CAAA,CAAA;AAAA,KAC7D;AAGA,IAAA,OAAO,iBAAiB,OAAO,CAAA,CAAA;AAAA,GACjC,CAAA;AAEA,EAAO,OAAA,OAAA,CAAA;AACT,CAAA;AAKA,MAAM,qBAAwB,GAAA,GAAA,CAAA;AAK9B,SAAS,iBAAiB,OAAyB,EAAA;AACjD,EAAA,IAAI,CAAC,OAAA,CAAQ,MAAQ,EAAA,OAAO,EAAC,CAAA;AAG7B,EAAM,MAAA,SAAA,GAAY,QAAQ,MAAO,CAAA,CAAC,KAAK,CAAM,KAAA,GAAA,GAAM,CAAE,CAAA,MAAA,EAAQ,CAAC,CAAA,CAAA;AAC9D,EAAA,IAAI,YAAY,qBAAuB,EAAA;AACrC,IAAQ,OAAA,CAAA,IAAA;AAAA,MACN,CAAA,wBAAA,EAA2B,SAAU,CAAA,cAAA,EAAgB,CAAA,wDAAA,CAAA;AAAA,KAEvD,CAAA;AAAA,GACF;AAEA,EAAI,IAAA,MAAA,GAAgB,CAAC,IAAI,CAAA,CAAA;AACzB,EAAA,KAAA,MAAW,UAAU,OAAS,EAAA;AAC5B,IAAA,MAAM,OAAc,EAAC,CAAA;AACrB,IAAA,KAAA,MAAW,WAAW,MAAQ,EAAA;AAC5B,MAAA,KAAA,MAAW,QAAQ,MAAQ,EAAA;AACzB,QAAK,IAAA,CAAA,IAAA,CAAK,WAAW,IAAO,GAAA,IAAA,GAAO,EAAE,GAAG,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA,CAAA;AAAA,OAC5D;AAAA,KACF;AACA,IAAS,MAAA,GAAA,IAAA,CAAA;AAAA,GACX;AACA,EAAO,OAAA,MAAA,CAAA;AACT,CAAA;AAGO,SAAS,WAAW,IAA2C,EAAA;AACpE,EAAI,IAAA,KAAA,CAAM,OAAQ,CAAA,IAAI,CAAG,EAAA;AACvB,IAAA,MAAM,SAAiB,EAAC,CAAA;AACxB,IAAA,KAAA,MAAW,OAAO,IAAM,EAAA;AACtB,MAAA,MAAA,CAAO,GAAU,CAAI,GAAA,GAAA,CAAA;AAAA,KACvB;AACA,IAAO,OAAA,MAAA,CAAA;AAAA,GACT,MAAA,IAAW,OAAO,IAAA,KAAS,QAAU,EAAA;AACnC,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAA,OAAO,EAAE,CAAC,IAAI,GAAG,IAAY,EAAA,CAAA;AAC/B;;;;"}
package/dist/es/fill.js CHANGED
@@ -5,11 +5,18 @@ function fill(keys) {
5
5
  const keysArray = singleOrArray(keys);
6
6
  const replaceMap = {};
7
7
  return items.map((d) => {
8
- const obj = {...d};
8
+ let needsCopy = false;
9
9
  for (const key of keysArray) {
10
- if (obj[key] != null) {
11
- replaceMap[key] = obj[key];
10
+ if (d[key] != null) {
11
+ replaceMap[key] = d[key];
12
12
  } else if (replaceMap[key] != null) {
13
+ needsCopy = true;
14
+ }
15
+ }
16
+ if (!needsCopy) return d;
17
+ const obj = { ...d };
18
+ for (const key of keysArray) {
19
+ if (obj[key] == null && replaceMap[key] != null) {
13
20
  obj[key] = replaceMap[key];
14
21
  }
15
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fill.js","sources":["../../src/fill.ts"],"sourcesContent":["import { SingleOrArray, singleOrArray } from './helpers/singleOrArray';\nimport { Key, TidyFn } from './types';\n\n/**\n * Fills values for the specified keys to match the last seen value in the collection.\n */\nexport function fill<T extends object>(keys: SingleOrArray<Key>): TidyFn<T> {\n const _fill: TidyFn<T> = (items: T[]): T[] => {\n const keysArray = singleOrArray(keys);\n\n const replaceMap: Partial<T> = {};\n\n return items.map((d) => {\n const obj = { ...d };\n for (const key of keysArray) {\n if (obj[key as keyof T] != null) {\n replaceMap[key as keyof T] = obj[key as keyof T];\n } else if (replaceMap[key as keyof T] != null) {\n obj[key as keyof T] = replaceMap[key as keyof T] as any;\n }\n }\n return obj;\n });\n };\n\n return _fill;\n}\n"],"names":[],"mappings":";;cAMuC;AACrC,QAAM,QAAmB,CAAC;AACxB,UAAM,YAAY,cAAc;AAEhC,UAAM,aAAyB;AAE/B,WAAO,MAAM,IAAI,CAAC;AAChB,YAAM,MAAM,IAAK;AACjB,iBAAW,OAAO;AAChB,YAAI,IAAI,QAAmB;AACzB,qBAAW,OAAkB,IAAI;AAAA,mBACxB,WAAW,QAAmB;AACvC,cAAI,OAAkB,WAAW;AAAA;AAAA;AAGrC,aAAO;AAAA;AAAA;AAIX,SAAO;AAAA;;;;"}
1
+ {"version":3,"file":"fill.js","sources":["../../src/fill.ts"],"sourcesContent":["import { SingleOrArray, singleOrArray } from './helpers/singleOrArray';\nimport { Key, TidyFn } from './types';\n\n/**\n * Fills values for the specified keys to match the last seen value in the collection.\n */\nexport function fill<T extends object>(keys: SingleOrArray<Key>): TidyFn<T> {\n const _fill: TidyFn<T> = (items: T[]): T[] => {\n const keysArray = singleOrArray(keys);\n\n const replaceMap: Partial<T> = {};\n\n return items.map((d) => {\n let needsCopy = false;\n for (const key of keysArray) {\n if (d[key as keyof T] != null) {\n replaceMap[key as keyof T] = d[key as keyof T];\n } else if (replaceMap[key as keyof T] != null) {\n needsCopy = true;\n }\n }\n if (!needsCopy) return d;\n const obj = { ...d };\n for (const key of keysArray) {\n if (obj[key as keyof T] == null && replaceMap[key as keyof T] != null) {\n obj[key as keyof T] = replaceMap[key as keyof T] as any;\n }\n }\n return obj;\n });\n };\n\n return _fill;\n}\n"],"names":[],"mappings":";;AAMO,SAAS,KAAuB,IAAqC,EAAA;AAC1E,EAAM,MAAA,KAAA,GAAmB,CAAC,KAAoB,KAAA;AAC5C,IAAM,MAAA,SAAA,GAAY,cAAc,IAAI,CAAA,CAAA;AAEpC,IAAA,MAAM,aAAyB,EAAC,CAAA;AAEhC,IAAO,OAAA,KAAA,CAAM,GAAI,CAAA,CAAC,CAAM,KAAA;AACtB,MAAA,IAAI,SAAY,GAAA,KAAA,CAAA;AAChB,MAAA,KAAA,MAAW,OAAO,SAAW,EAAA;AAC3B,QAAI,IAAA,CAAA,CAAE,GAAc,CAAA,IAAK,IAAM,EAAA;AAC7B,UAAW,UAAA,CAAA,GAAc,CAAI,GAAA,CAAA,CAAE,GAAc,CAAA,CAAA;AAAA,SACpC,MAAA,IAAA,UAAA,CAAW,GAAc,CAAA,IAAK,IAAM,EAAA;AAC7C,UAAY,SAAA,GAAA,IAAA,CAAA;AAAA,SACd;AAAA,OACF;AACA,MAAI,IAAA,CAAC,WAAkB,OAAA,CAAA,CAAA;AACvB,MAAM,MAAA,GAAA,GAAM,EAAE,GAAG,CAAE,EAAA,CAAA;AACnB,MAAA,KAAA,MAAW,OAAO,SAAW,EAAA;AAC3B,QAAA,IAAI,IAAI,GAAc,CAAA,IAAK,QAAQ,UAAW,CAAA,GAAc,KAAK,IAAM,EAAA;AACrE,UAAI,GAAA,CAAA,GAAc,CAAI,GAAA,UAAA,CAAW,GAAc,CAAA,CAAA;AAAA,SACjD;AAAA,OACF;AACA,MAAO,OAAA,GAAA,CAAA;AAAA,KACR,CAAA,CAAA;AAAA,GACH,CAAA;AAEA,EAAO,OAAA,KAAA,CAAA;AACT;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"filter.js","sources":["../../src/filter.ts"],"sourcesContent":["import { TidyFn } from './types';\n\n/**\n * Filters items\n * @param filterFn Returns true to keep the item, false to filter out\n */\nexport function filter<T extends object, O extends T>(\n filterFn: (item: T, index: number, array: T[]) => item is O\n): TidyFn<T, O>;\nexport function filter<T extends object>(\n filterFn: (item: T, index: number, array: T[]) => boolean\n): TidyFn<T>;\nexport function filter<T extends object>(\n filterFn: (item: T, index: number, array: T[]) => boolean\n): TidyFn<T> {\n const _filter: TidyFn<T> = (items: T[]): T[] => items.filter(filterFn);\n return _filter;\n}\n"],"names":[],"mappings":"gBAaE;AAEA,QAAM,UAAqB,CAAC,UAAoB,MAAM,OAAO;AAC7D,SAAO;AAAA;;;;"}
1
+ {"version":3,"file":"filter.js","sources":["../../src/filter.ts"],"sourcesContent":["import { TidyFn } from './types';\n\n/**\n * Filters items\n * @param filterFn Returns true to keep the item, false to filter out\n */\nexport function filter<T extends object, O extends T>(\n filterFn: (item: T, index: number, array: T[]) => item is O\n): TidyFn<T, O>;\nexport function filter<T extends object>(\n filterFn: (item: T, index: number, array: T[]) => boolean\n): TidyFn<T>;\nexport function filter<T extends object>(\n filterFn: (item: T, index: number, array: T[]) => boolean\n): TidyFn<T> {\n const _filter: TidyFn<T> = (items: T[]): T[] => items.filter(filterFn);\n return _filter;\n}\n"],"names":[],"mappings":"AAYO,SAAS,OACd,QACW,EAAA;AACX,EAAA,MAAM,OAAqB,GAAA,CAAC,KAAoB,KAAA,KAAA,CAAM,OAAO,QAAQ,CAAA,CAAA;AACrE,EAAO,OAAA,OAAA,CAAA;AACT;;;;"}
@@ -1,33 +1,36 @@
1
- import { autodetectByMap, makeByMap, isMatch } from './innerJoin.js';
1
+ import { autodetectByMap, makeByMap, buildJoinIndex, computeKey } from './innerJoin.js';
2
2
 
3
3
  function fullJoin(itemsToJoin, options) {
4
4
  const _fullJoin = (items) => {
5
- if (!itemsToJoin.length)
6
- return items;
7
- if (!items.length)
8
- return itemsToJoin;
5
+ if (!itemsToJoin.length) return items;
6
+ if (!items.length) return itemsToJoin;
9
7
  const byMap = (options == null ? void 0 : options.by) == null ? autodetectByMap(items, itemsToJoin) : makeByMap(options.by);
10
- const matchMap = new Map();
8
+ const joinKeys = Object.keys(byMap);
9
+ const itemKeys = joinKeys.map((jKey) => byMap[jKey]);
10
+ const index = buildJoinIndex(itemsToJoin, joinKeys);
11
+ const matchedItems = /* @__PURE__ */ new Set();
11
12
  const joinObjectKeys = Object.keys(itemsToJoin[0]);
12
13
  const joined = items.flatMap((d) => {
13
- const matches = itemsToJoin.filter((j) => {
14
- const matched = isMatch(d, j, byMap);
15
- if (matched) {
16
- matchMap.set(j, true);
14
+ const key = computeKey(d, itemKeys);
15
+ const matches = index.get(key);
16
+ if (matches !== void 0) {
17
+ for (const j of matches) {
18
+ matchedItems.add(j);
17
19
  }
18
- return matched;
19
- });
20
- if (matches.length) {
21
- return matches.map((j) => ({...d, ...j}));
20
+ return matches.map((j) => ({ ...d, ...j }));
22
21
  }
23
- const undefinedFill = Object.fromEntries(joinObjectKeys.filter((key) => d[key] == null).map((key) => [key, void 0]));
24
- return {...d, ...undefinedFill};
22
+ const undefinedFill = Object.fromEntries(
23
+ joinObjectKeys.filter((key2) => d[key2] == null).map((key2) => [key2, void 0])
24
+ );
25
+ return { ...d, ...undefinedFill };
25
26
  });
26
- if (matchMap.size < itemsToJoin.length) {
27
- const leftEmptyObject = Object.fromEntries(Object.keys(items[0]).map((key) => [key, void 0]));
27
+ if (matchedItems.size < itemsToJoin.length) {
28
+ const leftEmptyObject = Object.fromEntries(
29
+ Object.keys(items[0]).map((key) => [key, void 0])
30
+ );
28
31
  for (const item of itemsToJoin) {
29
- if (!matchMap.has(item)) {
30
- joined.push({...leftEmptyObject, ...item});
32
+ if (!matchedItems.has(item)) {
33
+ joined.push({ ...leftEmptyObject, ...item });
31
34
  }
32
35
  }
33
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fullJoin.js","sources":["../../src/fullJoin.ts"],"sourcesContent":["import { Datum, TidyFn } from './types';\nimport { isMatch, makeByMap, autodetectByMap, JoinOptions } from './innerJoin';\nimport { O } from 'ts-toolbelt';\n\n/**\n * Performs a full join on two collections\n * @param itemsToJoin The rows/items to be appended to end of collection\n */\nexport function fullJoin<T extends Datum, JoinT extends Datum>(\n itemsToJoin: JoinT[],\n options?: JoinOptions<JoinT, T> | null | undefined\n): TidyFn<T, O.Merge<T, Partial<JoinT>>> {\n const _fullJoin: TidyFn<T, O.Merge<T, Partial<JoinT>>> = (\n items: T[]\n ): O.Merge<T, Partial<JoinT>>[] => {\n if (!itemsToJoin.length) return items as any;\n if (!items.length) return itemsToJoin as any;\n\n // convert by option in to a map from T key to JoinT key\n const byMap =\n options?.by == null\n ? autodetectByMap(items, itemsToJoin)\n : makeByMap(options.by);\n\n // keep track of what has been matched\n const matchMap = new Map();\n\n // when we miss a join, we want to explicitly add in undefined\n // so our rows all have the same keys. get those keys here.\n const joinObjectKeys = Object.keys(itemsToJoin[0]);\n\n const joined = items.flatMap((d: T) => {\n const matches = itemsToJoin.filter((j: JoinT) => {\n const matched = isMatch(d, j, byMap);\n if (matched) {\n matchMap.set(j, true);\n }\n return matched;\n });\n\n if (matches.length) {\n return matches.map((j: JoinT) => ({ ...d, ...j }));\n }\n\n // add in missing keys explicitly as undefined without\n // overriding existing values and while maintaining order\n // of keys\n const undefinedFill = Object.fromEntries(\n joinObjectKeys\n .filter((key) => d[key] == null)\n .map((key) => [key, undefined])\n );\n\n return { ...d, ...undefinedFill };\n });\n\n // add in the ones we missed\n if (matchMap.size < itemsToJoin.length) {\n const leftEmptyObject = Object.fromEntries(\n Object.keys(items[0]).map((key) => [key, undefined])\n );\n for (const item of itemsToJoin) {\n if (!matchMap.has(item)) {\n joined.push({ ...leftEmptyObject, ...item });\n }\n }\n }\n\n return joined;\n };\n return _fullJoin;\n}\n"],"names":[],"mappings":";;kBASE,aACA;AAEA,QAAM,YAAmD,CACvD;AAEA,QAAI,CAAC,YAAY;AAAQ,aAAO;AAChC,QAAI,CAAC,MAAM;AAAQ,aAAO;AAG1B,UAAM,QACJ,oCAAS,OAAM,OACX,gBAAgB,OAAO,eACvB,UAAU,QAAQ;AAGxB,UAAM,WAAW,IAAI;AAIrB,UAAM,iBAAiB,OAAO,KAAK,YAAY;AAE/C,UAAM,SAAS,MAAM,QAAQ,CAAC;AAC5B,YAAM,UAAU,YAAY,OAAO,CAAC;AAClC,cAAM,UAAU,QAAQ,GAAG,GAAG;AAC9B,YAAI;AACF,mBAAS,IAAI,GAAG;AAAA;AAElB,eAAO;AAAA;AAGT,UAAI,QAAQ;AACV,eAAO,QAAQ,IAAI,CAAC,WAAmB,MAAM;AAAA;AAM/C,YAAM,gBAAgB,OAAO,YAC3B,eACG,OAAO,CAAC,QAAQ,EAAE,QAAQ,MAC1B,IAAI,CAAC,QAAQ,CAAC,KAAK;AAGxB,aAAO,IAAK,MAAM;AAAA;AAIpB,QAAI,SAAS,OAAO,YAAY;AAC9B,YAAM,kBAAkB,OAAO,YAC7B,OAAO,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK;AAE3C,iBAAW,QAAQ;AACjB,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,IAAK,oBAAoB;AAAA;AAAA;AAAA;AAK3C,WAAO;AAAA;AAET,SAAO;AAAA;;;;"}
1
+ {"version":3,"file":"fullJoin.js","sources":["../../src/fullJoin.ts"],"sourcesContent":["import { Datum, TidyFn } from './types';\nimport {\n makeByMap,\n autodetectByMap,\n JoinOptions,\n buildJoinIndex,\n computeKey,\n} from './innerJoin';\nimport { Merge } from './type-utils';\n\n/**\n * Performs a full join on two collections\n * @param itemsToJoin The rows/items to be appended to end of collection\n */\nexport function fullJoin<T extends Datum, JoinT extends Datum>(\n itemsToJoin: JoinT[],\n options?: JoinOptions<JoinT, T> | null | undefined\n): TidyFn<T, Merge<T, Partial<JoinT>>> {\n const _fullJoin: TidyFn<T, Merge<T, Partial<JoinT>>> = (\n items: T[]\n ): Merge<T, Partial<JoinT>>[] => {\n if (!itemsToJoin.length) return items as any;\n if (!items.length) return itemsToJoin as any;\n\n // convert by option in to a map from T key to JoinT key\n const byMap =\n options?.by == null\n ? autodetectByMap(items, itemsToJoin)\n : makeByMap(options.by);\n\n const joinKeys = Object.keys(byMap);\n const itemKeys = joinKeys.map((jKey) => byMap[jKey] as string);\n const index = buildJoinIndex(itemsToJoin, joinKeys);\n\n // keep track of matched join items by reference\n const matchedItems = new Set<JoinT>();\n\n // when we miss a join, we want to explicitly add in undefined\n // so our rows all have the same keys. get those keys here.\n const joinObjectKeys = Object.keys(itemsToJoin[0]);\n\n const joined = items.flatMap((d: T) => {\n const key = computeKey(d, itemKeys);\n const matches = index.get(key);\n\n if (matches !== undefined) {\n for (const j of matches) {\n matchedItems.add(j);\n }\n return matches.map((j: JoinT) => ({ ...d, ...j }));\n }\n\n // add in missing keys explicitly as undefined without\n // overriding existing values and while maintaining order\n // of keys\n const undefinedFill = Object.fromEntries(\n joinObjectKeys\n .filter((key) => d[key] == null)\n .map((key) => [key, undefined])\n );\n\n return { ...d, ...undefinedFill };\n });\n\n // add in the ones we missed\n if (matchedItems.size < itemsToJoin.length) {\n const leftEmptyObject = Object.fromEntries(\n Object.keys(items[0]).map((key) => [key, undefined])\n );\n for (const item of itemsToJoin) {\n if (!matchedItems.has(item)) {\n joined.push({ ...leftEmptyObject, ...item });\n }\n }\n }\n\n return joined;\n };\n return _fullJoin;\n}\n"],"names":["key"],"mappings":";;AAcgB,SAAA,QAAA,CACd,aACA,OACqC,EAAA;AACrC,EAAM,MAAA,SAAA,GAAiD,CACrD,KAC+B,KAAA;AAC/B,IAAI,IAAA,CAAC,WAAY,CAAA,MAAA,EAAe,OAAA,KAAA,CAAA;AAChC,IAAI,IAAA,CAAC,KAAM,CAAA,MAAA,EAAe,OAAA,WAAA,CAAA;AAG1B,IAAM,MAAA,KAAA,GAAA,CACJ,OAAS,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,OAAA,CAAA,EAAA,KAAM,IACX,GAAA,eAAA,CAAgB,OAAO,WAAW,CAAA,GAClC,SAAU,CAAA,OAAA,CAAQ,EAAE,CAAA,CAAA;AAE1B,IAAM,MAAA,QAAA,GAAW,MAAO,CAAA,IAAA,CAAK,KAAK,CAAA,CAAA;AAClC,IAAA,MAAM,WAAW,QAAS,CAAA,GAAA,CAAI,CAAC,IAAS,KAAA,KAAA,CAAM,IAAI,CAAW,CAAA,CAAA;AAC7D,IAAM,MAAA,KAAA,GAAQ,cAAe,CAAA,WAAA,EAAa,QAAQ,CAAA,CAAA;AAGlD,IAAM,MAAA,YAAA,uBAAmB,GAAW,EAAA,CAAA;AAIpC,IAAA,MAAM,cAAiB,GAAA,MAAA,CAAO,IAAK,CAAA,WAAA,CAAY,CAAC,CAAC,CAAA,CAAA;AAEjD,IAAA,MAAM,MAAS,GAAA,KAAA,CAAM,OAAQ,CAAA,CAAC,CAAS,KAAA;AACrC,MAAM,MAAA,GAAA,GAAM,UAAW,CAAA,CAAA,EAAG,QAAQ,CAAA,CAAA;AAClC,MAAM,MAAA,OAAA,GAAU,KAAM,CAAA,GAAA,CAAI,GAAG,CAAA,CAAA;AAE7B,MAAA,IAAI,YAAY,KAAW,CAAA,EAAA;AACzB,QAAA,KAAA,MAAW,KAAK,OAAS,EAAA;AACvB,UAAA,YAAA,CAAa,IAAI,CAAC,CAAA,CAAA;AAAA,SACpB;AACA,QAAO,OAAA,OAAA,CAAQ,IAAI,CAAC,CAAA,MAAc,EAAE,GAAG,CAAA,EAAG,GAAG,CAAA,EAAI,CAAA,CAAA,CAAA;AAAA,OACnD;AAKA,MAAA,MAAM,gBAAgB,MAAO,CAAA,WAAA;AAAA,QAC3B,cACG,CAAA,MAAA,CAAO,CAACA,IAAAA,KAAQ,EAAEA,IAAG,CAAA,IAAK,IAAI,CAAA,CAC9B,IAAI,CAACA,IAAAA,KAAQ,CAACA,IAAAA,EAAK,MAAS,CAAC,CAAA;AAAA,OAClC,CAAA;AAEA,MAAA,OAAO,EAAE,GAAG,CAAG,EAAA,GAAG,aAAc,EAAA,CAAA;AAAA,KACjC,CAAA,CAAA;AAGD,IAAI,IAAA,YAAA,CAAa,IAAO,GAAA,WAAA,CAAY,MAAQ,EAAA;AAC1C,MAAA,MAAM,kBAAkB,MAAO,CAAA,WAAA;AAAA,QAC7B,MAAO,CAAA,IAAA,CAAK,KAAM,CAAA,CAAC,CAAC,CAAA,CAAE,GAAI,CAAA,CAAC,GAAQ,KAAA,CAAC,GAAK,EAAA,KAAA,CAAS,CAAC,CAAA;AAAA,OACrD,CAAA;AACA,MAAA,KAAA,MAAW,QAAQ,WAAa,EAAA;AAC9B,QAAA,IAAI,CAAC,YAAA,CAAa,GAAI,CAAA,IAAI,CAAG,EAAA;AAC3B,UAAA,MAAA,CAAO,KAAK,EAAE,GAAG,eAAiB,EAAA,GAAG,MAAM,CAAA,CAAA;AAAA,SAC7C;AAAA,OACF;AAAA,KACF;AAEA,IAAO,OAAA,MAAA,CAAA;AAAA,GACT,CAAA;AACA,EAAO,OAAA,SAAA,CAAA;AACT;;;;"}
@@ -12,9 +12,13 @@ function groupBy(groupKeys, fns, options) {
12
12
  } else if (arguments.length === 2 && fns != null && !Array.isArray(fns)) {
13
13
  options = fns;
14
14
  }
15
- const _groupBy = (items) => {
15
+ const _groupBy = ((items) => {
16
16
  const grouped = makeGrouped(items, groupKeys);
17
- const results = runFlow(grouped, fns, options == null ? void 0 : options.addGroupKeys);
17
+ const results = runFlow(
18
+ grouped,
19
+ fns,
20
+ options == null ? void 0 : options.addGroupKeys
21
+ );
18
22
  if (options == null ? void 0 : options.export) {
19
23
  switch (options.export) {
20
24
  case "grouped":
@@ -38,29 +42,33 @@ function groupBy(groupKeys, fns, options) {
38
42
  }
39
43
  const ungrouped = ungroup(results, options == null ? void 0 : options.addGroupKeys);
40
44
  return ungrouped;
41
- };
45
+ });
42
46
  return _groupBy;
43
47
  }
44
- groupBy.grouped = (options) => ({...options, export: "grouped"});
45
- groupBy.entries = (options) => ({...options, export: "entries"});
46
- groupBy.entriesObject = (options) => ({...options, export: "entries-object"});
47
- groupBy.object = (options) => ({...options, export: "object"});
48
- groupBy.map = (options) => ({...options, export: "map"});
49
- groupBy.keys = (options) => ({...options, export: "keys"});
50
- groupBy.values = (options) => ({...options, export: "values"});
51
- groupBy.levels = (options) => ({...options, export: "levels"});
48
+ groupBy.grouped = (options) => ({ ...options, export: "grouped" });
49
+ groupBy.entries = (options) => ({ ...options, export: "entries" });
50
+ groupBy.entriesObject = (options) => ({ ...options, export: "entries-object" });
51
+ groupBy.object = (options) => ({ ...options, export: "object" });
52
+ groupBy.map = (options) => ({ ...options, export: "map" });
53
+ groupBy.keys = (options) => ({ ...options, export: "keys" });
54
+ groupBy.values = (options) => ({ ...options, export: "values" });
55
+ groupBy.levels = (options) => ({ ...options, export: "levels" });
52
56
  function runFlow(items, fns, addGroupKeys) {
53
57
  let result = items;
54
- if (!(fns == null ? void 0 : fns.length))
55
- return result;
58
+ if (!(fns == null ? void 0 : fns.length)) return result;
56
59
  for (const fn of fns) {
57
- if (!fn)
58
- continue;
60
+ if (!fn) continue;
59
61
  result = groupMap(result, (items2, keys) => {
60
- const context = {groupKeys: keys};
62
+ const keysSnapshot = keys.slice();
63
+ const context = { groupKeys: keysSnapshot };
61
64
  let leafItemsMapped = fn(items2, context);
62
65
  if (addGroupKeys !== false) {
63
- leafItemsMapped = leafItemsMapped.map((item) => assignGroupKeys(item, keys));
66
+ const filteredKeys = keysSnapshot.filter(
67
+ (key) => typeof key[0] !== "function" && key[0] != null
68
+ );
69
+ leafItemsMapped = leafItemsMapped.map(
70
+ (item) => assignGroupKeys(item, keysSnapshot, filteredKeys)
71
+ );
64
72
  }
65
73
  return leafItemsMapped;
66
74
  });
@@ -68,9 +76,9 @@ function runFlow(items, fns, addGroupKeys) {
68
76
  return result;
69
77
  }
70
78
  function makeGrouped(items, groupKeys) {
71
- const groupKeyFns = singleOrArray(groupKeys).map((key, i) => {
79
+ const groupKeyFns = singleOrArray(groupKeys).map((key) => {
72
80
  const keyFn = typeof key === "function" ? key : (d) => d[key];
73
- const keyCache = new Map();
81
+ const keyCache = /* @__PURE__ */ new Map();
74
82
  return (d) => {
75
83
  const keyValue = keyFn(d);
76
84
  const keyValueOf = isObject(keyValue) ? keyValue.valueOf() : keyValue;
@@ -90,7 +98,10 @@ function ungroup(grouped, addGroupKeys) {
90
98
  groupTraversal(grouped, items, [], identity, (root, keys, values) => {
91
99
  let valuesToAdd = values;
92
100
  if (addGroupKeys !== false) {
93
- valuesToAdd = values.map((d) => assignGroupKeys(d, keys));
101
+ const filteredKeys = keys.filter(
102
+ (key) => typeof key[0] !== "function" && key[0] != null
103
+ );
104
+ valuesToAdd = values.map((d) => assignGroupKeys(d, keys, filteredKeys));
94
105
  }
95
106
  root.push(...valuesToAdd);
96
107
  });
@@ -111,23 +122,30 @@ function processFromGroupsOptions(options) {
111
122
  compositeKey = (_a = options.compositeKey) != null ? _a : defaultCompositeKey;
112
123
  }
113
124
  const groupFn = (values, keys) => {
114
- return single ? mapLeaf(addGroupKeys === false ? values[0] : assignGroupKeys(values[0], keys)) : mapLeaves(values.map((d) => mapLeaf(addGroupKeys === false ? d : assignGroupKeys(d, keys))));
125
+ return single ? mapLeaf(
126
+ addGroupKeys === false ? values[0] : assignGroupKeys(values[0], keys)
127
+ ) : mapLeaves(
128
+ values.map(
129
+ (d) => mapLeaf(addGroupKeys === false ? d : assignGroupKeys(d, keys))
130
+ )
131
+ );
115
132
  };
116
133
  const keyFn = flat ? (keys) => compositeKey(keys.map((d) => d[1])) : (keys) => keys[keys.length - 1][1];
117
- return {groupFn, keyFn};
134
+ return { groupFn, keyFn };
118
135
  }
119
136
  function exportLevels(grouped, options) {
120
- const {groupFn, keyFn} = processFromGroupsOptions(options);
121
- let {mapEntry = identity} = options;
122
- const {levels = ["entries"]} = options;
137
+ const { groupFn, keyFn } = processFromGroupsOptions(options);
138
+ let { mapEntry = identity } = options;
139
+ const { levels = ["entries"] } = options;
123
140
  const levelSpecs = [];
124
141
  for (const levelOption of levels) {
125
142
  switch (levelOption) {
143
+ // entries / entries-object -----------------------------------------
126
144
  case "entries":
127
145
  case "entries-object":
128
146
  case "entries-obj":
129
147
  case "entriesObject": {
130
- const levelMapEntry = (levelOption === "entries-object" || levelOption === "entries-obj" || levelOption === "entriesObject") && options.mapEntry == null ? ([key, values]) => ({key, values}) : mapEntry;
148
+ const levelMapEntry = (levelOption === "entries-object" || levelOption === "entries-obj" || levelOption === "entriesObject") && options.mapEntry == null ? ([key, values]) => ({ key, values }) : mapEntry;
131
149
  levelSpecs.push({
132
150
  id: "entries",
133
151
  createEmptySubgroup: () => [],
@@ -140,10 +158,11 @@ function exportLevels(grouped, options) {
140
158
  });
141
159
  break;
142
160
  }
161
+ // map -------------------------------------------------------------
143
162
  case "map":
144
163
  levelSpecs.push({
145
164
  id: "map",
146
- createEmptySubgroup: () => new Map(),
165
+ createEmptySubgroup: () => /* @__PURE__ */ new Map(),
147
166
  addSubgroup: (parentGrouped, newSubgroup, key) => {
148
167
  parentGrouped.set(key, newSubgroup);
149
168
  },
@@ -152,6 +171,7 @@ function exportLevels(grouped, options) {
152
171
  }
153
172
  });
154
173
  break;
174
+ // object ----------------------------------------------------------
155
175
  case "object":
156
176
  levelSpecs.push({
157
177
  id: "object",
@@ -164,6 +184,7 @@ function exportLevels(grouped, options) {
164
184
  }
165
185
  });
166
186
  break;
187
+ // keys ------------------------------------------------------------
167
188
  case "keys":
168
189
  levelSpecs.push({
169
190
  id: "keys",
@@ -176,6 +197,7 @@ function exportLevels(grouped, options) {
176
197
  }
177
198
  });
178
199
  break;
200
+ // values ----------------------------------------------------------
179
201
  case "values":
180
202
  levelSpecs.push({
181
203
  id: "values",
@@ -188,6 +210,7 @@ function exportLevels(grouped, options) {
188
210
  }
189
211
  });
190
212
  break;
213
+ // custom ----------------------------------------------------------
191
214
  default: {
192
215
  if (typeof levelOption === "object") {
193
216
  levelSpecs.push(levelOption);
@@ -209,7 +232,12 @@ function exportLevels(grouped, options) {
209
232
  const addLeaf = (parentGrouped, keys, values, level) => {
210
233
  var _a;
211
234
  const levelSpec = (_a = levelSpecs[level]) != null ? _a : levelSpecs[levelSpecs.length - 1];
212
- levelSpec.addLeaf(parentGrouped, keyFn(keys), groupFn(values, keys), level);
235
+ levelSpec.addLeaf(
236
+ parentGrouped,
237
+ keyFn(keys),
238
+ groupFn(values, keys),
239
+ level
240
+ );
213
241
  };
214
242
  const initialOutputObject = levelSpecs[0].createEmptySubgroup();
215
243
  return groupTraversal(grouped, initialOutputObject, [], addSubgroup, addLeaf);