Finding optimal mapping patterns that transform relational data into a linear format
Some slight improvements:


You could do without the result array (less state ).
I think using vanilla object destructuring is more clear than the lowdash reduce method which is confusing to me (unless I still don't understand it and my code actually is not equivalent to yours ).


const allNodes = [
];

const rootNode = {
};

function initializeNodeMapper(nodes) {
  return function mapNodes(node) {
    const propertyIds = node.properties.map(({ id }) =&gt; id);
    const currentNode = nodes.find(({ id }) =&gt; id === node.id);
    const nodeWithFilteredProperties = {
      ...currentNode,
      properties: currentNode.properties.filter(({ id }) =&gt;
        propertyIds.includes(id)
      )
    };

    return node.children
      ? [nodeWithFilteredProperties].concat(node.children.map(mapNodes))
      : [nodeWithFilteredProperties];
  };
}

const mappedData = initializeNodeMapper(allNodes)(rootNode);


Update:

Are you looking for something like this?

const nodes = [
];

const rootNode = {
};

const pipe = (...fns) =&gt; x =&gt; fns.reduce((v, f) =&gt; f(v), x);

const getFlattenedNodes = node =&gt;
  node.children
    ? [node].concat(
        node.children.reduce(
          (acc, val) =&gt; acc.concat(getFlattenedNodes(val)),
          []
        )
      )
    : [node];

const getPropertyIds = node =&gt; node.properties.map(({ id }) =&gt; id);

const getNodeWithProperties = nodesWithProperties =&gt; node =&gt;
  nodesWithProperties.find(({ id }) =&gt; id === node.id);

const getNodesWithFilteredProperties = propertyIdsAndNodesToBeFiltered =&gt;
  propertyIdsAndNodesToBeFiltered.map(([propertyIds, nodeWithProperties]) =&gt; ({
    ...nodeWithProperties,
    properties: nodeWithProperties.properties.filter(({ id }) =&gt;
      propertyIds.includes(id)
    )
  }));

const getPropertyIdsAndNodes = nodesWithProperties =&gt; flattenNodes =&gt;
  flattenNodes.map(node =&gt; [
    getPropertyIds(node),
    getNodeWithProperties(nodesWithProperties)(node)
  ]);

const mappedData = pipe(
  getFlattenedNodes,
  getPropertyIdsAndNodes(nodes),
  getNodesWithFilteredProperties
)(rootNode);