Is there a way to merge all these filters into one? Or another way to make it more effective? Or just use for loop?
driving = value.filter((obj) => obj.type === CalendarEventType.MIND && obj.data.practice === 'driving').length;
breathWork = value.filter((obj) => obj.type === CalendarEventType.MIND && obj.data.practice === 'breath work').length;
meditation = value.filter((obj) => obj.type === CalendarEventType.MIND && obj.data.practice === 'meditation').length;
cooking = value.filter((obj) => obj.type === CalendarEventType.MIND && obj.data.practice === 'cooking').length;
walking = value.filter((obj) => obj.type === CalendarEventType.MIND && obj.data.practice === 'walking').length;
other = value.filter((obj) => obj.type === CalendarEventType.MIND && obj.data.practice === 'other').length;
They look to me very redudant.
CodePudding user response:
Currently you're looping 6 times over the same array. You can reduce the runtime with a simple for-loop or reduce:
const counts = value.reduce((acc, el) => {
if (el.type !== CalendarEventType.MIND) return acc;
acc[el.data.practice] = (acc[el.data.practice] ?? 0) 1
return acc;
}, {});
Example:
const CalendarEventType = {
MIND: 1,
OTHER: 2
};
const value = [
{type: CalendarEventType.MIND, data: { practice: 'driving' } },
{type: CalendarEventType.MIND, data: { practice: 'breath work' } },
{type: CalendarEventType.OTHER, data: { practice: 'breath work' } },
{type: CalendarEventType.MIND, data: { practice: 'other' } },
{type: CalendarEventType.MIND, data: { practice: 'other' } },
{type: CalendarEventType.OTHER, data: { practice: 'other' } },
];
const counts = value.reduce((acc, el) => {
if (el.type !== CalendarEventType.MIND) return acc;
acc[el.data.practice] = (acc[el.data.practice] ?? 0) 1
return acc;
}, {});
console.log(counts);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
One possible way would be to group by data.practice
. Since there's no native "group by" function, you could implement it yourself (as described here), or you could use a library like Lodash or Ramda.
Example, using Lodash's groupBy
:
const filteredItems = value.filter((obj) => obj.type === CalendarEventType.MIND);
const groupedItems = groupBy(filteredItems, obj => obj.data.practice);
Then you can do whatever you want with groupedItems
, e.g.:
driving = groupedItems['driving'] ? groupedItems['driving'].length : 0;
Note that if a given value for data.practice
is not represented in filteredItems
, then that key won't be present in groupedItems
- hence the need to check for that key.
CodePudding user response:
You could take an array of values and use a single filter.
const
practices = ['driving', 'breath work', 'meditation', 'cooking', 'walking', 'other'];
filter = ({ type, data: { practice } }) => type === CalendarEventType.MIND && practices.includes(practice),
result = value.filter(filter),
count = values.reduce((sum, o) => sum filter(o), 0);