Reduce an object containing arrays as values to single array

Viewed 87

Question: Reduce an object containing arrays as values to single array based on a condition. Details: I have an object containing arrays as values.

{
  514:["564"],
  812:["514"],
  1006:["921","812"],
  1012: ["1002"],
  1024:["6994","7992"],
  6923:["1024","1006"],
  6994:["1012","7182"],
  7992:["5921"],
}

I want to write a javascript function that can reduce this object to array based on key I am passing to function. The result array should have the id that we passed to function and it's value in object and also any other values corresponding to the values till the time we can find no keys. For example: If I pass 6994, then I need result from function as following array

["6994", "1012", "7182", "1002"]

I tried and got the following to work. Wanted to know if there is a better more efficient solution:

function getChildIds({ treeMap, id }) {
  let childIds = [id];
  let parentIds = [id];
  while(!!parentIds.length) {
    let tempIds = [];
    parentIds.forEach((parentId, index) => {
      if(!!treeMap[parentId]) {
        tempIds.push(...treeMap[parentId]);
        childIds.push(...treeMap[parentId]);
      }
    });
    parentIds = tempIds;
  }
  return childIds;
}

Edit: Recursion is not preferred since this object can be quite huge and running out of browser stack memory is not desirable.

1 Answers

You could get the nested nodes from the given node.

Type: Depth-first search: In-order (LNR)

const
    getNodes = node => [node, ...(nodes[node] || []).flatMap(getNodes)],
    nodes = { 514: ["564"], 812: ["514"], 1006: ["921", "812"], 1012: ["1002"],  1024: ["6994", "7992"], 6923: ["1024", "1006"], 6994: ["1012", "7182"], 7992: ["5921"] },
    node = "6994",
    result = getNodes(node);

console.log(result);

Another approach uses a stack, which might be faster than the above recursive reduce approach.

The order of this approach is different, because the tree traversal is in level order (breadth-first search).

const
    getNodes = node => {
        const
            stack = [node],
            result = [];

        while (stack.length) {
            const
                n = stack.shift();
            result.push(n);
            if (!nodes[n]) continue;
            stack.push(...nodes[n]);                   
        }
        return result; 
    },
    nodes = { 514: ["564"], 812: ["514"], 1006: ["921", "812"], 1012: ["1002"],  1024: ["6994", "7992"], 6923: ["1024", "1006"], 6994: ["1012", "7182"], 7992: ["5921"] },
    node = "6994",
    result = getNodes(node);

console.log(result);

Related