SharePointBeginner
SharePointBeginner

Reputation: 359

Combine two similar functions to one

I have two functions that are very similar, with some small differences I want to combine:

private filterByOperationType() {
    let operationBuffer: IProductOperation[] = [];
    if (this.filterConditions[0].selected.length > 0) {
      operationBuffer = this.operations.filter(({ operationDetails }) => {
          let operationType = false;
          for (const details of this.filterConditions) {
            if (details.name === 'Type') {
              const parsedGroup = details.selected[0].text;
              if (parsedGroup === operationDetails) {
                operationType = true;
              }
            }
          }
          return operationType;
        });
      }
    return operationBuffer;
  }

  /** Filter the operations by function group when dropdown is used */
  private filterByFunctionGroup() {
    const filteredData = this.operations.filter(({ functionDetails }) => {
      let groupDescriptionMatch = false;
      for (const details of this.filterConditions) {
        if (!details.selected[0]) {
          return;
        }
        if (details.name === 'Function group') {
          const parsedGroup = details.selected[0].text.match(/[a-zA-Z]+/g);
          if (parsedGroup?.join(' ') === functionDetails) {
            groupDescriptionMatch = true;
          }
        }
      }
      return groupDescriptionMatch;
    });
    return filteredData;
  }
}

Both of the functions are filtering the same object, but different keys (type and functiongroup). Function groups value is modified with regex as the dropdown value includes a index number and dash which is not used in the logic. Example:

1 - myFunctionGroup --regex-->myFunctionGroup

This is not done in the type key. How to combine these two functions?

Upvotes: 0

Views: 314

Answers (1)

windowsill
windowsill

Reputation: 3649

So I thought what you were struggling with was separation of concerns, not reusability/abstraction. I had to rewrite things a bit so it was readable to me, and it turns out most of the work you're doing can be replaced with language constructs so you're only left with the business logic.

Once you're left with only the business logic, it's easy to see that it's simple enough that no refactoring is needed.

const filterByOperationType = () => {
  if (!filterConditions[0].selected.length) {
    return [];
  }

  return operations.filter(({ operationDetails }) => {
    return filterConditions.some(fc =>
      fc.name === "Type" && fc.selected[0].text === operationDetails,
    );
  });
};

/** Filter the operations by function group when dropdown is used */
const filterByFunctionGroup = () => {
  if (!filterConditions[0].selected.length) {
    return [];
  }

  return operations.filter(({ functionDetails }) => {
    return filterConditions.some(fc =>
      fc.name === "Function group"
      && intoLetterOnlyWords(fc.selected[0].text) === functionDetails,
    );
  });
};

// Do some weird stuff to some letters
const intoLetterOnlyWords = (text) => text.match(/[a-zA-Z]+/g).join(" ");

If you want to take it further, make a hof to close over the concerns of each filter function.


const createFilterBy = (nameToMatch: string, formatSelectedText = (t: string) => t) => () => {
  if (!filterConditions[0].selected.length) {
    return [];
  }

  return operations.filter(({ functionDetails }) => {
    return filterConditions.some(fc =>
      fc.name === nameToMatch
      && formatSelectedText(fc.selected[0].text) === functionDetails,
    );
  });
};

// Do some weird stuff to some letters
const intoLetterOnlyWords = (text: string) => text.match(/[a-zA-Z]+/g).join(" ");

const filterByFunctionGroup = createFilterBy("Function group", intoLetterOnlyWords);
const filterByOperationType = createFilterBy("Type");

Upvotes: 2

Related Questions