Search code examples
javascriptlodashflatmap

use flatmap on javascript, with condition


I am creating a component which handles watch and edit permissions. The data structure I use to hold the permissions looks like this:

const input = [{
    isAllowed: true,
    permissionType: "watch",
    userId: 14
  },
  {
    isAllowed: false,
    permissionType: "edit",
    userId: 14
  },
  {
    isAllowed: true,
    permissionType: "edit",
    userId: 24
  },
  {
    isAllowed: false,
    permissionType: "edit",
    userId: 34
  },
  {
    isAllowed: false,
    permissionType: "watch",
    userId: 44
  },
  {
    isAllowed: false,
    permissionType: "edit",
    userId: 44
  }
]

At first, I just wanted to get a list of all users with any permissions given at all, so I would use

let managers = _.flatMap(props.settings.managerPermissions, (p) => p.userId);
managers = [...new Set(managers)];

So this would leave me with managers = [14,24,34,44], but I need to edit this flatmap in a way that I would not get back the id of a manager which has no permissions at all, even if they were added to the list already, so in this case the return value of the new flatmap should be managers = [14,24]. (ofcourse flatMap is not a must here and if there's a better way to do it I would be happy to see it)


Solution

  • You only need flatMap when the result of map would be an array of arrays, and you want a flat array.

    In this case filter the array by isAllowed and then map to userId:

    const arr = [{"isAllowed":true,"permissionType":"watch","userId":14},{"isAllowed":false,"permissionType":"edit","userId":14},{"isAllowed":true,"permissionType":"edit","userId":24},{"isAllowed":false,"permissionType":"edit","userId":34},{"isAllowed":false,"permissionType":"watch","userId":44},{"isAllowed":false,"permissionType":"edit","userId":44}]
    
    const managers = [...new Set(
      arr
      .filter(o => o.isAllowed)
      .map(o => o.userId)
    )]
    
    console.log(managers)

    However, you can actually use Array.flatMap() (or lodash equivalent) to map and filter at the same time. It's less idiomatic the map/filter combo, and I'm not sure about the performance, so I don't use it myself. The idea is to return an empty array for items that you don't want:

    const arr = [{"isAllowed":true,"permissionType":"watch","userId":14},{"isAllowed":false,"permissionType":"edit","userId":14},{"isAllowed":true,"permissionType":"edit","userId":24},{"isAllowed":false,"permissionType":"edit","userId":34},{"isAllowed":false,"permissionType":"watch","userId":44},{"isAllowed":false,"permissionType":"edit","userId":44}]
    
    const managers = [...new Set(
      arr.flatMap(o => o.isAllowed ? o.userId : [])
    )]
    
    console.log(managers)