0

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?

1
  • 2
    They're too different IMO. Generalizing them, if there are only 2, would probably be more confusing than useful. Commented Jul 1, 2021 at 22:54

1 Answer 1

2

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");
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.