Neil Merton
Neil Merton

Reputation: 573

Filter a JavaScript array of object another JavaScript array of objects

I have the following made-up JavaScript array of objects:

const permissions = [
  {
    moduleEnabled: true,
    moduleId: 1,
    moduleName: 'Directory'
  },
  {
    moduleEnabled: true,
    moduleId: 2,
    moduleName: 'Time off'
  },
  {
    moduleEnabled: false,
    moduleId: 3,
    moduleName: 'Tasks'
  },
  {
    moduleEnabled: false,
    moduleId: 4,
    moduleName: 'Documents'
  }
]

I also have the following array of objects based on a collection of widgets that are available to be displayed:

const widgets = [
  {
    id: 1,
    moduleId: 2,
    title: 'Your time off'
  },
  {
    id: 2,
    moduleId: 1,
    title: 'Your colleagues'
  },
  {
    id: 3,
    moduleId: 3,
    title: 'Your tasks'
  },
  {
    id: 4,
    moduleId: 5,
    title: 'Your sales pipeline'
  },
  {
    id: 5,
    moduleId: 4,
    title: 'Your documents'
  },
  {
    id: 6,
    moduleId: 6,
    title: 'Your legal cases'
  }
]

What I'd like to do is to reduce the array of objects widgets to a new array of objects filteredWidgets based on the values in the permissions array of objects, these being whether the moduleId is found, and also where the moduleEnabled is true.

I've tried the code below, but it's not working:

const filteredWidgets = []
for (const permission in permissions) {
  const found = widgets.filter((item) => item.moduleId === permission.moduleId && permission.moduleEnabled)
  if (found) {
    filteredWidgets.push(found)
  }
}
console.log('filteredWidgets\n', filteredWidgets)

Any help will be greatly appreciated. Thanks in advance.

Edit: include expected output:

const filteredWidgets = [
  {
    id: 1,
    moduleId: 2,
    title: 'Your time off'
  },
  {
    id: 2,
    moduleId: 1,
    title: 'Your colleagues'
  }
]

Upvotes: 2

Views: 97

Answers (4)

Alex L
Alex L

Reputation: 4241

I have a solution using reduce

But first, you have to create a Map and use that to create an Object with Object.fromEntries(), and then finally use the reduce.

const permissions = [
  {
    moduleEnabled: true,
    moduleId: 1,
    moduleName: 'Directory'
  },
  {
    moduleEnabled: true,
    moduleId: 2,
    moduleName: 'Time off'
  },
  {
    moduleEnabled: false,
    moduleId: 3,
    moduleName: 'Tasks'
  },
  {
    moduleEnabled: false,
    moduleId: 4,
    moduleName: 'Documents'
  }
]

const widgets = [
  {
    id: 1,
    moduleId: 2,
    title: 'Your time off'
  },
  {
    id: 2,
    moduleId: 1,
    title: 'Your colleagues'
  },
  {
    id: 3,
    moduleId: 3,
    title: 'Your tasks'
  },
  {
    id: 4,
    moduleId: 5,
    title: 'Your sales pipeline'
  },
  {
    id: 5,
    moduleId: 4,
    title: 'Your documents'
  },
  {
    id: 6,
    moduleId: 6,
    title: 'Your legal cases'
  }
]

const permissonsMap = permissions.map((child,index) => {
  return [child.moduleId, {...child}]
})

const permissionsObj = Object.fromEntries(permissonsMap);

//console.log(permissionsObj);

const filteredWidgets = widgets.reduce((aggArr,currItem) => {
  if (permissionsObj[currItem.moduleId] && permissionsObj[currItem.moduleId].moduleEnabled){
    aggArr.push(currItem);
  }
  return aggArr;
},[])

console.log(filteredWidgets);

Important lines are:

const permissonsMap = permissions.map((child,index) => {
  return [child.moduleId, {...child}]
})

const permissionsObj = Object.fromEntries(permissonsMap);

//console.log(permissionsObj);

const filteredWidgets = widgets.reduce((aggArr,currItem) => {
  if (permissionsObj[currItem.moduleId] && permissionsObj[currItem.moduleId].moduleEnabled){
    aggArr.push(currItem);
  }
  return aggArr;
},[])

console.log(filteredWidgets);

Upvotes: 0

Mike D Sutton
Mike D Sutton

Reputation: 806

In your filter function, check for any permission which matches the given criteria:

const filteredWidgets = widgets.filter(widget =>
    permissions.find(permission =>
        (permission.moduleId === widget.moduleId) && permission.moduleEnabled));

Upvotes: 2

Nina Scholz
Nina Scholz

Reputation: 386520

You could take an object with the allowed ids and filter by moduleId.

const
    permissions = [{ moduleEnabled: true, moduleId: 1, moduleName: 'Directory' }, { moduleEnabled: true, moduleId: 2, moduleName: 'Time off' }, { moduleEnabled: false, moduleId: 3, moduleName: 'Tasks' }, { moduleEnabled: false, moduleId: 4, moduleName: 'Documents' }],
    widgets = [{ id: 1, moduleId: 2, title: 'Your time off' }, { id: 2, moduleId: 1, title: 'Your colleagues' }, { id: 3, moduleId: 3, title: 'Your tasks' }, { id: 4, moduleId: 5, title: 'Your sales pipeline' }, { id: 5, moduleId: 4, title: 'Your documents' }, { id: 6, moduleId: 6, title: 'Your legal cases' }],
    allowed = permissions.reduce((o, { moduleEnabled, moduleId }) =>
        ({ ...o, [moduleId]: moduleEnabled }), {}),
    filteredWidgets = widgets.filter(({ moduleId }) => allowed[moduleId]);

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

Upvotes: 0

norbitrial
norbitrial

Reputation: 15166

I think with .reduce() and .find() combination the following can work for you:

const permissions = [{moduleEnabled: true, moduleId: 1, moduleName: 'Directory' }, { moduleEnabled: true, moduleId: 2,  moduleName: 'Time off' }, { moduleEnabled: false,  moduleId: 3, moduleName: 'Tasks' }, { moduleEnabled: false,  moduleId: 4, moduleName: 'Documents' }];
const widgets = [{ id: 1, moduleId: 2, title: 'Your time off' }, { id: 2, moduleId: 1, title: 'Your colleagues' }, { id: 3,  moduleId: 3, title: 'Your tasks' }, { id: 4, moduleId: 5, title: 'Your sales pipeline' }, { id: 5, moduleId: 4, title: 'Your documents' },{ id: 6, moduleId: 6, title: 'Your legal cases'}]

const result = widgets.reduce((a, c) => {
  const found = permissions.find(e => e.moduleId === c.moduleId)
  return found && found.moduleEnabled ? a.concat(c) : a;
}, []);

console.log(result);

I hope this helps!

Upvotes: 1

Related Questions