JavaSa
JavaSa

Reputation: 6242

Elegant way to shorten if statement

Any ideas how to shorten if statment in an elegant way.
My if statement:

 if(getfoo1() == getfoo2() &&  getfoo2() == 1)
 {

 }

EDIT:
I'm looking for something like:

if(getfoo1() == getfoo2() ==1)
{
}

But I suppose we can't do this.

Upvotes: 0

Views: 103

Answers (6)

Ahmet Emrebas
Ahmet Emrebas

Reputation: 944

Just an alternative to if-else-statement

Sometimes you need to put lots of if-else statements in code which causes some readability problems. The following technique might help you make your code more readable. It creates type guards as the if-statement does so you are not checking the same value twice. Also, this technique indicates the intention of our code more clearly

type MatchReturn<T, C, R> = Omit<
  Matcher<Exclude<T, C>, R>,
  'matchHandle' | 'match'
>;

type MatchHanle<T, C, R> = Omit<
  Matcher<Exclude<T, C>, R>,
  'matchReturn' | 'match' | 'get'
>;

export class MatcherOptions<T> {
  defaultValue: (() => T) | null = null;
  throwError = false;

  constructor(options?: Partial<MatcherOptions<T>>) {
    Object.assign(this, options);
  }
}
/**
 * Utilize the Matcher class to eliminate cumbersome if-else statements.
 */
export class Matcher<T, R> {
  private matchResult: (() => R) | null = null;
  private updated = false;

  /**
   * When the throwError parameter is set to true, an error will be thrown by get method if there is no match to the value.
   * @param value
   * @param throwError boolean
   */
  constructor(
    private readonly value: T,
    private readonly options: Partial<MatcherOptions<R>> = new MatcherOptions()
  ) {
    this.options = new MatcherOptions(options);
  }

  /**
   * Return true if the matchValue is identical to the value; otherwise, return false.
   * @param matchValue T
   * @returns boolean
   */
  match(matchValue: T): boolean {
    return matchValue === this.value;
  }

  /**
   * If the matchValue is equivalent to the value,
   * proceed to assign the result to the returnValue variable.
   * Subsequently, at the conclusion of the statement,
   * you can access the value stored in returnValue using the get method.
   * @param matchValue T
   * @param returnValue R
   * @returns R
   */
  matchReturn<C extends T>(
    matchValue: C,
    returnValue: () => R
  ): MatchReturn<T, C, R> {
    if (this.match(matchValue)) {
      this.matchResult = returnValue;
      this.updated = true;
    }
    return this as MatchReturn<T, C, R>;
  }

  /**
   * If the matchValue is equal to the value, proceed to invoke the provided handler function.
   * @param matchValue T
   * @param handler ()=>any
   * @returns Matcher
   */
  matchHandle<C extends T = T>(
    matchValue: C,
    handler: () => unknown
  ): MatchHanle<T, C, R> {
    if (this.match(matchValue)) {
      handler();
    }
    return this as MatchHanle<T, C, R>;
  }

  /**
   * Upon finalizing the matchReturn method chain, employ this method to retrieve the resultant output.
   * @returns R
   */
  get() {
    if (this.options.throwError) {
      if (!this.updated) {
        throw new Error(`We could not find mach for ${this.value}!`);
      }
    }

    if (this.options.defaultValue) {
      if (!this.updated) {
        return this.options.defaultValue();
      }
    }

    return this.reset();
  }

  private reset() {
    if (this.matchResult) {
      const result = this.matchResult();
      this.matchResult = null;
      return result;
    }
    return null;
  }
}

Example

Let's use our matcher.


      type InputType = 'a' | 'b' | 'c'; 
      type ReturnType= 100 | 200  | 300;


      const abcMatcher = new Matcher<InputType , ReturnType>('a');

      // result will be 100.
      const result = abcMatcher

        // Shows autocompletes for inputs and outputs
        .matchReturn('a', () => 100)
        .matchReturn('b', () => 200)
        .matchReturn('c', () => 200)

        // You are not allowed to check the same value again! 
        // Shows error message
        .matchReturn('a', () => 'letter a')

         // get the result
        .get();

Upvotes: 0

RajivRisi
RajivRisi

Reputation: 398

Try this.

$a = getfoo1();
$b = getfoo2();
if( intval($a && $b) === 1) {
    echo 'hi';
}

Upvotes: 0

Derek
Derek

Reputation: 4751

Since we don't know the possible return values from the functions, if you assume they are integers then you can say:

$a = getfoo1();
$b = getfoo2();
if (($a * $b) === 1) { // strict equality for the win
    echo 'hi';
}

The result would only be true iff both $a AND $b are 1.

Another way:

$both = array(getfoo1(), getfoo2());
// use array_diff_assoc so it checks multiple occurrences of the same value
$diffCount = count(array_diff_assoc($both, array(1, 1))); 
if ($diffCount === 0) {
    echo 'hi';
}

Upvotes: 1

Since anyway getfoo2() == 1 must be true, a better approach is to first check whether getfoo2() is equal to 1. If it false no matter about 2nd condition. But If you first check getfoo1() == getfoo2() and and then check getfoo2() == 1 you have to check 2 conditions all the times.

Therefore go for

$a = getfoo1();
$b = getfoo2();
if($b == 1 && $a == $b) 
{
     // logiv
}
else
{
}

Upvotes: 0

BlitZ
BlitZ

Reputation: 12168

$a = getfoo1();
$b = getfoo2(); // less operations, while it not produces duplicate calls

if($a == $b && $b == 1){
    // do something
}

Upvotes: 3

Luka
Luka

Reputation: 1718

$variable = ((getfoo1() == getfoo2() && getfoo2() == 1) ? $value1 : $value2);

More elegant, combined:

$a = getfoo1();
$b = getfoo2();
$variable = (($a == $b && $b == 1) ? $value1 : $value2);

Upvotes: 2

Related Questions