0
\$\begingroup\$

I have a list of events. They are html elements. The premium events have a data attribute in their parent element: data-premium-event.

I need to separate the events in two lists:

  1. a list of premium events
  2. a list of regular (non-premium) events

I then show oder hide them using the logic in handleVisibleEvents. The method works correctly but I would like to refactor it while it has a high cognitive complexity.

     this.nrOfRegularEventsDisplayed = 0;
     this.nrOfPremiumEventsDisplayed = 0;
     this.regularEventsToShow = [];
     this.premiumEventsToShow = [];
     this.refreshActiveCategoryTags();
     const events = toArray(this.elements['event']);
     if (events) {
         if (this.loadEventsButton) {
             show(this.loadEventsButton);
         }
         events.forEach((event) => {
             if (event.dataset.eventTags.includes(this.activeCategory.dataset.categoryTag)) {
                 if (event.parentElement.getAttribute('data-premium-event') !== null) {
                     this.premiumEventsToShow.push(event);
                 } else {
                     this.regularEventsToShow.push(event);
                 }
             } else {
                 hide(event.parentElement);
             }
         });
         this.handleVisibleEvents(TagsFilteringOverview.VISIBLE_EVENTS, false);
     }


\$\endgroup\$
1
  • \$\begingroup\$ Do you really need to show the loadEventsButton only if events evaluates to true? \$\endgroup\$
    – cyberbrain
    Commented Mar 1, 2023 at 10:24

1 Answer 1

0
\$\begingroup\$

A common name for such operation is partition. An implementation of it might look something like

const fold = to => fun => iterable =>
  Array.prototype.reduce.call(iterable, fun, to)

const partition = pred => fold ([[], []]) ((acc, x) =>
  (acc[pred(x) ? 0 : 1].push(x), acc))

so that given a predicate

const hasPremium = el => el.parentElement.dataset?.premiumEvent

and example data

const data = [
  {parentElement: {dataset: {premiumEvent: true}}}
  , {parentElement: {}}
  , {parentElement: {}}
  , {parentElement: {}}
  , {parentElement: {dataset: {premiumEvent: true}}}
  , {parentElement: {}}
  , {parentElement: {}}
  , {parentElement: {dataset: {premiumEvent: true}}}
  , {parentElement: {dataset: {premiumEvent: true}}}
]

the usage becomes

console.log(partition (hasPremium) (data))
\$\endgroup\$
3
  • \$\begingroup\$ Thanks so much @morbusg Thanks so much for your review. I am not familiar with the syntax to => fun => iterable => Array.prototype.reduce.call(iterable, fun, to) Can you please explain. Thanks in advance. \$\endgroup\$
    – scura s
    Commented Mar 6, 2023 at 6:27
  • \$\begingroup\$ @scuras It's just calling the n-ary reduce function as curried unary form, to enable partial application and calling on any iterable objects (having length, like HTMLCollection) instead of being restricted to just arrays. \$\endgroup\$
    – morbusg
    Commented Mar 6, 2023 at 15:29
  • \$\begingroup\$ Thank you very much @morbusg \$\endgroup\$
    – scura s
    Commented Mar 10, 2023 at 6:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.