Guest User

Untitled

a guest
Apr 16th, 2018
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.60 KB | None | 0 0
  1. import { map, filter, reduce, assign } from 'lodash';
  2.  
  3. /**
  4. * Map over a tree from the bottom-most nodes up. Applies transformation to deepest children,
  5. * then to parents, and so on. You can even rename the property that contains the children.
  6. *
  7. * Usage:
  8. * tmap(
  9. * x => ({ ...x, value: x.value + 1 || 0 }),
  10. * 'children',
  11. * [{value: 0, children: []}, {children: [{value: 5, children: [{value: 100}]}]}]
  12. * )
  13. * // This will increment all values by 1 or initialize value to 0.
  14. */
  15. export const tmap = <T extends { [key: string]: T[] | any }, R>(
  16. transformation: (t: T) => R,
  17. children: keyof T,
  18. nodes: T[],
  19. ): R[] => {
  20. return map(nodes, node => {
  21. if (node[children] !== undefined) {
  22. const newNode = assign({}, node, { [children]: tmap<T, R>(transformation, children, node[children]) });
  23. return transformation(newNode);
  24. }
  25. return transformation(node);
  26. });
  27. };
  28.  
  29. /**
  30. * Filter over a tree from bottom-most nodes up. Applies predicate to deepest children,
  31. * then to parents, and so on. So rolling up empty children arrays is possible.
  32. */
  33. export const tfilter = <T extends { [key: string]: T[] | any }>(
  34. predicate: (t: T) => boolean,
  35. children: keyof T,
  36. nodes: T[],
  37. ): T[] => {
  38. if (Array.isArray(nodes)) {
  39. return reduce(
  40. nodes,
  41. (acc, node) => {
  42. if (node[children] !== undefined) {
  43. const newNode = assign({}, node, { [children]: tfilter<T>(predicate, children, node[children]) });
  44. return predicate(newNode) ? [...acc, newNode] : acc;
  45. }
  46. return predicate(node) ? [...acc, node] : acc;
  47. },
  48. <T[]>[],
  49. );
  50. }
  51. return nodes;
  52. };
Add Comment
Please, Sign In to add comment