Home > Software design >  Can those codes be simplified?
Can those codes be simplified?

Time:08-20

I have written this program, but I am not sure whether it can be simplified. Thanks,

Code:

function detect(a, b, c) {
    if (a.length === 0 && b.length === 0 && c.length === 0) {
        return 0;
    } else if (a.length > 0 && b.length === 0 && c.length === 0) {
        return 1;
    } else if (a.length === 0 && b.length > 0 && c.length === 0) {
        return 2;
    } else if (a.length === 0 && b.length === 0 && c.length > 0) {
        return 3;
    } else if (a.length > 0 && b.length > 0 && c.length === 0) {
        return 4;
    } else if (a.length === 0 && b.length > 0 && c.length > 0) {
        return 5;
    } else if (a.length > 0 && b.length === 0 && c.length > 0) {
        return 6;
    } else if (a.length > 0 && b.length > 0 && c.length > 0) {
        return 7;
    }
}

CodePudding user response:

Drop the elses:

function detect(a, b, c) {
    if (a.length === 0 && b.length === 0 && c.length === 0) return 0;
    if (a.length > 0 && b.length === 0 && c.length === 0) return 1;
    if (a.length === 0 && b.length > 0 && c.length === 0) return 2;
    if (a.length === 0 && b.length === 0 && c.length > 0) return 3;
    if (a.length > 0 && b.length > 0 && c.length === 0) return 4;
    if (a.length === 0 && b.length > 0 && c.length > 0) return 5;
    if (a.length > 0 && b.length === 0 && c.length > 0) return 6;
    if (a.length > 0 && b.length > 0 && c.length > 0) return 7;
}

Use variables for shared expressions:

function detect(a, b, c) {
    const aEmpty = a.length === 0;
    const bEmpty = b.length === 0;
    const cEmpty = c.length === 0;
    if ( aEmpty &&  bEmpty &&  cEmpty) return 0;
    if (!aEmpty &&  bEmpty &&  cEmpty) return 1;
    if ( aEmpty && !bEmpty &&  cEmpty) return 2;
    if ( aEmpty &&  bEmpty && !cEmpty) return 3;
    if (!aEmpty && !bEmpty &&  cEmpty) return 4;
    if ( aEmpty && !bEmpty && !cEmpty) return 5;
    if (!aEmpty &&  bEmpty && !cEmpty) return 6;
    if (!aEmpty && !bEmpty && !cEmpty) return 7;
}

Reorder to form a binary counter pattern:

function detect(a, b, c) {
    const aEmpty = a.length === 0;
    const bEmpty = b.length === 0;
    const cEmpty = c.length === 0;
    if (!aEmpty && !bEmpty && !cEmpty) return 7;
    if (!aEmpty && !bEmpty &&  cEmpty) return 4;
    if (!aEmpty &&  bEmpty && !cEmpty) return 6;
    if (!aEmpty &&  bEmpty &&  cEmpty) return 1;
    if ( aEmpty && !bEmpty && !cEmpty) return 5;
    if ( aEmpty && !bEmpty &&  cEmpty) return 2;
    if ( aEmpty &&  bEmpty && !cEmpty) return 3;
    if ( aEmpty &&  bEmpty &&  cEmpty) return 0;
}

Create the index using a bit operation formula:

function detect(a, b, c) {
    const aEmpty = a.length === 0;
    const bEmpty = b.length === 0;
    const cEmpty = c.length === 0;
    const index = aEmpty << 2 | bEmpty << 1 | cEmpty << 0;
    if (index === 0) return 7;
    if (index === 1) return 4;
    if (index === 2) return 6;
    if (index === 3) return 1;
    if (index === 4) return 5;
    if (index === 5) return 2;
    if (index === 6) return 3;
    if (index === 7) return 0;
}

Just index into an array:

function detect(a, b, c) {
    const aEmpty = a.length === 0;
    const bEmpty = b.length === 0;
    const cEmpty = c.length === 0;
    const index = aEmpty << 2 | bEmpty << 1 | cEmpty << 0;
    const array = [7, 4, 6, 1, 5, 2, 3, 0];
    return array[index]
}

Optionally, get rid of the temporary variables:

const detect = (a, b, c) => [7, 4, 6, 1, 5, 2, 3, 0][(a.length === 0) << 2 | (b.length === 0) << 1 | (c.length === 0) << 0];

Golf further to just

const detect=(a,b,c)=>[0,3,2,5,1,6,4,7][!a.length<<2|!b.length<<1|!c.length]

Choose whichever level of conciseness you are comfortable with. I would however recommend a version that clearly (either through code or formatting) points out the pattern.

CodePudding user response:

This is the simplest version I can come up with:

function detect(a, b, c) {
    return [0,1,2,4,3,6,5,7][(a.length>0)|((b.length>0)<<1)|((c.length>0)<<2)];
}

// test methods:
console.log(detect([], [], [])   ' '   detect([1], [], []));
console.log(detect([], [1], [])   ' '   detect([], [], [1]));
console.log(detect([1], [1], [])   ' '   detect([], [1], [1]));
console.log(detect([1], [], [1])   ' '   detect([1], [1], [1]));

CodePudding user response:

function detect(a, b, c) {
    result=0;
    if (a.length > 0){
        result=result 1;
    }
    if (b.length > 0){
        result=result 2;
    }
    if (c.length > 0){
        result=result 4;
    }
    returnList=[0,1,2,4,3,6,5,7];
    return returnList[result];
}

This function should work as same.

Although I feel this is ugly.

CodePudding user response:

Another way to approach these types of problems is to hardcode condition -> result maps.

function detect(a, b, c) {
  const aIndex = a.length > 0 ? 1 : 0;
  const bIndex = b.length > 0 ? 1 : 0;
  const cIndex = c.length > 0 ? 1 : 0;
  const conditionMap = [
    [
      [0, 3],
      [2, 5],
    ],
    [
      [1, 6],
      [4, 7],
    ]
  ]
  console.log(`(${a.length}, ${b.length}, ${c.length}):`, conditionMap[aIndex][bIndex][cIndex]);
  return conditionMap[aIndex][bIndex][cIndex];
}

console.log("For (a, b, c) lengths:");
detect([], [], []);
detect([1], [], []);
detect([], [1, 1], []);
detect([], [], [1]);
detect([1], [1], []);
detect([], [1], [1]);
detect([1], [], [1]);
detect([1], [1], [1, 0]);

  • Related