javascripttruthiness

What is the simplest way to compare truthiness in this specific way?


Given the following instructions I have created a function that achieves the requirements. I feel my function is a bit too complex, though it does what it's supposed to. The difficult part for myself was avoiding the equality operators. The only way I could think to solve this is with a bit of math and a comparison operator. How can I simplify this function and save some editing time? Thanks in advance.

Write a function onlyOne that accepts three arguments of any type.

onlyOne should return true only if exactly one of the three arguments are truthy. Otherwise, it should return false.

Do not use the equality operators (== and ===) in your solution.

My function:

function onlyOne(input1, input2, input3) {
    output = false;
    let truthy = 0;
    let falsey = 0;

    if (!!input1) {
        truthy++;
    } else {
        falsey++;
    }

    if (!!input2) {
        truthy++;
    } else {
        falsey++;
    }

    if (!!input3) {
        truthy++;
    } else {
        falsey++;
    }

    if (falsey > truthy) {
        output = true;
    }
    if (falsey > 2) {
        output = false;
    }
    return output;
}

Solution

  • I would call Boolean on each argument and reduce into a number, and then check the truthyness of that number minus one:

    const onlyOne = (...args) => {
      const numTruthy = args.reduce((a, arg) => a + Boolean(arg), 0);
      return !Boolean(numTruthy - 1);
    };
    console.log(onlyOne(0, 0, 0));
    console.log(onlyOne(0, 0, 1));
    console.log(onlyOne(0, 1, 1));
    console.log(onlyOne(1, 1, 1));

    Or, for a more concise but less understandable version, you can integrate the 1 into the initial value provided to reduce:

    const onlyOne = (...args) => !args.reduce((a, arg) => a + Boolean(arg), -1);
    
    console.log(onlyOne(0, 0, 0));
    console.log(onlyOne(0, 0, 1));
    console.log(onlyOne(0, 1, 1));
    console.log(onlyOne(1, 1, 1));