Search code examples
javascriptarraysecmascript-6javascript-objectsecmascript-2016

Reduce recursively pushing only once


I am trying to run a reduce method recursively on an array of objects.

I start with an string and push the object that matches that string then I see what object that entry ReportsTo, once I get that object I push it and kepp on checking recursively who that object ReportsTo next till it reaches the max Rank in this case of 3.

But it does not push beyond the first one.

const data = [
  {
    Name: 'Peter',
    ReportsTo: '',
    Rank: 1
  },
  {
    Name: 'Tom',
    ReportsTo: 'Peter',
    Rank: 2
  },
  {
    Name: 'Maria',
    ReportsTo: 'Tom',
    Rank: 3
  },
  {
    Name: 'John',
    ReportsTo: 'Peter',
    Rank: 3
  },
  {
    Name: 'Fiona',
    ReportsTo: 'Maria',
    Rank: 4
  }
]

const findManager = (person) => data.reduce((total, current) => {
  if (current.Name === person) {
    total.push(current)
    if (current.Rank > 2) {
      findManager(current.ReportsTo)
    }
  }  
  
  return total
}, [])

console.log(findManager('Fiona'))
.as-console-wrapper { max-height: 100% !important; top: 0; }

The desire output will be all the objects that are lower than 3 and that manage in this case Fiona

[ 
  { Name: 'Fiona', ReportsTo: 'Maria', Rank: 4 },
  { Name: 'Maria', ReportsTo: 'Tom', Rank: 3 },
  { Name: 'Tom', ReportsTo: 'Peter', Rank: 2 }
]

Solution

  • I don't really see the point in using reduce here. reduce is intended to provide some combined result from a series of values, but you are just looking for one value (and using a side-effect to accomplish it).

    I think this is a better approach:

    const findManagers = (name) => {
        const foundPerson = data.find(({ Name }) => Name === name);
        
        return foundPerson.Rank > 2
            ? [foundPerson, ...findManagers(foundPerson.ReportsTo)]
            : [foundPerson];
    };
    
    const data = [
      {
        Name: 'Peter',
        ReportsTo: '',
        Rank: 1
      },
      {
        Name: 'Tom',
        ReportsTo: 'Peter',
        Rank: 2
      },
      {
        Name: 'Maria',
        ReportsTo: 'Tom',
        Rank: 3
      },
      {
        Name: 'John',
        ReportsTo: 'Peter',
        Rank: 3
      },
      {
        Name: 'Fiona',
        ReportsTo: 'Maria',
        Rank: 4
      }
    ]
    
    console.log(findManagers('Fiona'))
    .as-console-wrapper { max-height: 100% !important; top: 0; }