* Takes an object with keys that are paths and combines the * keys that have similar prefixes. * Combining is done via the combiner function.
(pathedObject: any, combiner: any, pathIndex = 1)
| 285 | * Combining is done via the combiner function. |
| 286 | */ |
| 287 | collapsePaths(pathedObject: any, combiner: any, pathIndex = 1): any { |
| 288 | if (!this.options.collapse) { |
| 289 | // Don't do this if the --no-collapse flag is specified |
| 290 | return pathedObject; |
| 291 | } |
| 292 | const allSegments = Object.keys(pathedObject).map((path) => { |
| 293 | return path.split("/").filter((s) => { |
| 294 | return s !== ""; |
| 295 | }); |
| 296 | }); |
| 297 | const pathSegments = allSegments.filter((segments) => { |
| 298 | return segments.length > pathIndex; |
| 299 | }); |
| 300 | const otherSegments = allSegments.filter((segments) => { |
| 301 | return segments.length <= pathIndex; |
| 302 | }); |
| 303 | if (pathSegments.length === 0) { |
| 304 | return pathedObject; |
| 305 | } |
| 306 | const prefixes: Record<any, any> = {}; |
| 307 | // Count path prefixes for the index. |
| 308 | pathSegments.forEach((segments) => { |
| 309 | const prefixPath = pathString(segments.slice(0, pathIndex)); |
| 310 | const prefixCount = _.get(prefixes, prefixPath, new Set()); |
| 311 | prefixes[prefixPath] = prefixCount.add(segments[pathIndex]); |
| 312 | }); |
| 313 | const collapsedObject: Record<any, any> = {}; |
| 314 | pathSegments.forEach((segments) => { |
| 315 | const prefix = segments.slice(0, pathIndex); |
| 316 | const prefixPath = pathString(prefix); |
| 317 | const prefixCount = _.get(prefixes, prefixPath); |
| 318 | const originalPath = pathString(segments); |
| 319 | if (prefixCount.size >= COLLAPSE_THRESHOLD) { |
| 320 | const tail = segments.slice(pathIndex + 1); |
| 321 | const collapsedPath = pathString(prefix.concat(COLLAPSE_WILDCARD).concat(tail)); |
| 322 | const currentValue = collapsedObject[collapsedPath]; |
| 323 | if (currentValue) { |
| 324 | collapsedObject[collapsedPath] = combiner(currentValue, pathedObject[originalPath]); |
| 325 | } else { |
| 326 | collapsedObject[collapsedPath] = pathedObject[originalPath]; |
| 327 | } |
| 328 | } else { |
| 329 | collapsedObject[originalPath] = pathedObject[originalPath]; |
| 330 | } |
| 331 | }); |
| 332 | otherSegments.forEach((segments) => { |
| 333 | const originalPath = pathString(segments); |
| 334 | collapsedObject[originalPath] = pathedObject[originalPath]; |
| 335 | }); |
| 336 | // Do this again, but down a level. |
| 337 | return this.collapsePaths(collapsedObject, combiner, pathIndex + 1); |
| 338 | } |
| 339 | |
| 340 | renderUnindexedData() { |
| 341 | const table = new Table({ |
no test coverage detected