检查多个值是否全为假或全为真

31

如何检查20个变量是否全部为true或全部为false?

如果可能,不使用非常长的if语句来实现。

这些变量实际上是数组元素:

array('a'=> true, 'b'=> true ...)

为了更清楚地说明:

  • 如果数组同时包含true和false值,则返回空。
  • 如果数组只包含true值,则返回true。
  • 如果数组只包含false值,则返回false。 :)
11个回答

61
if(count(array_unique($your_array)) === 1)  
  return current($your_array);

else return;

13
@barfoon - 你可以考虑添加一点关于这里正在做什么的解释,这样可能会得到更多的赞同。但请注意不要改变原来的意思。 - Sandeepan Nath
5
我猜这里使用 array_unique 函数来删除所有重复的元素,然后检查数组中是否只剩下一个项,是的话就返回它。举例来说,如果数组只包含 true,那么经过 array_unique 处理后,我们将得到一个只有一个 true 元素的数组,没有其他元素了。 - TCB13
2
这样做会非常慢,所以如果你有大型数组(100个布尔值迭代100000次需要运行2.3秒),请注意。我很快就会发布基准测试结果,这个古老的问题引起了我的兴趣。 - Markus AO

31
你可以使用in_array函数。
例如,对于所有真值:
if(in_array(false, $array, true) === false){
    return true;
}
else if(in_array(true, $array, true) === false){
    return false;
}
else{
     return 'nothing';
}

2
我认为这个是最“合乎逻辑”的,将来几年后当你再次遇到时,你会立刻意识到你正在测试一个数组中的“false”和“true”。而被接受的答案需要更多的思考——“unique”……“count”……? - kasimir

20

可以像php.net的评论中所示,使用array_product

$check[] = boolval(TRUE);
$check[] = boolval(1);
$check[] = boolval(FALSE);
$check[] = boolval(0);

$result = (bool) array_product($check);
// $result is set to FALSE because only two of the four values evaluated to TRUE

15

虽然这个问题很古老,但是无妨。我想要对不同的方法进行基准测试。由于in_array()方法可能不需要迭代整个数组,所以它的表现最佳。 (即使最后只有一个唯一的布尔值,也很少需要迭代整个数组,但即便如此,它的性能仍然很好。)

这里没有提到的一种方法是array_sum($array),如果所有的值都是false,则返回0;如果存在true值,则返回1+。类似于使用array_filter的方法,它不能告诉您两者是否都存在,但用于查找任何内容是否为true非常有用。我还添加了一个基本的foreach检查混合或全部为真/假,以及一个只检查是否存在任何truein_array(如下面的*_bin)。

这里是基准测试结果。每个情况都会迭代10、100或1000个随机布尔值的数组100000次,并且再次迭代9、99和999个相同的布尔值,最后一个布尔值是唯一的(为了让in_array进行完整的迭代时间)。测试前三个检查产生请求的true/false/both结果,其余四个仅检查是否存在true值。


随机布尔数组

  • in_array: 10 bools = 0.16 sec
  • foreach: 10 bools = 0.122 sec
  • array_unique: 10 bools = 0.274 sec
  • foreach_bin: 10 bools = 0.095 sec
  • in_array_bin: 10 bools = 0.073 sec
  • array_sum: 10 bools = 0.074 sec
  • array_filter: 10 bools = 0.118 sec

  • in_array: 100 bools = 0.153 sec
  • foreach: 100 bools = 0.122 sec
  • array_unique: 100 bools = 2.3451 sec
  • foreach_bin: 100 bools = 0.094 sec
  • in_array_bin: 100 bools = 0.074 sec
  • array_sum: 100 bools = 0.126 sec
  • array_filter: 100 bools = 0.228 sec

  • in_array: 1000 bools = 0.154 sec
  • foreach: 1000 bools = 0.149 sec
  • array_unique: 1000 bools = 32.6659 sec (!!)
  • foreach_bin: 1000 bools = 0.075 sec
  • in_array_bin: 1000 bools = 0.074 sec
  • array_sum: 1000 bools = 0.8771 sec
  • array_filter: 1000 bools = 1.4021 sec

最后一个布尔值不同

  • in_array: 10 bools = 0.152 sec
  • foreach: 10 bools =
    function foreach_truth_test($array)
    {   
        $trues = $falses = false;
    
        foreach($array as $val) {
            if ($val === true) {
                $trues = true;
            } elseif ($val === false) {
                $falses = true;
            }
            if ($trues === true && $falses === true) {
                return 'both'; // Enough information.
            }
        }
    
        // Regular Universe
        if ($trues === true && $falses === false) {
            return 'true';
        } // Evil Mirror Universe
        elseif ($trues === false && $falses === true) {
            return 'false';
        } // Intergalactic Void
        else {
            return 'void'; // =^_^=
        }
    }
    

    顺便说一句,可以在上面使用 'null',但是这样读起来更有趣。在 Windows 上进行了基准测试,因此微秒读数不太精确。


备忘录:TL;DR = array_sum($array) > 0 - Potherca
2
@Pot 如果你只处理布尔值,那么在表达式中甚至不需要 > 0 - mickmackusa

6

此外,您可以拥有一个变量列表(不仅限于值数组),以检查所有值是否与某个特定值匹配。

$var1 = true;
$var2 = true;
$var3 = false;

$isAllVarsTrue = !in_array(false, [$var1, $var2, $var3], true);

var_dump($isAllVarsTrue); //false

5

如果你只存储布尔值,使用这个:

$a = array('a'=> true, 'b'=> true, 'c'=>true);
$af = array_filter($a);
if ($af == $a) {
    echo "all true";
}
if (empty($af)) {
    echo "all false";
}

注意:如果数组中有其他值,它们将根据 PHP 可怕的转换规则转换为布尔值。

4
一个简单的循环即可。注意,如果数组为空,则两个条件都满足(所有值均为 false 和 true)。由于有 else 子句,因此您不会在结果中看到这一点,但您可以自行确定如何处理这种情况。
// Input
$x = array ('a'=>false, 'b'=>false, 'c'=>false);

// Initialization
$anytrue = false;
$alltrue = true;

// Processing
foreach($x as $k=>$v)
{
    $anytrue |= $v;
    $alltrue &= $v;
}

// Display result
if ($alltrue)
  echo 'All elements are true';
elseif (!$anytrue)
  echo 'All elements are false';
else
  echo 'Mixed values';

3
如果它们都是包含true/false值的数组元素,则使用array_flip()函数:

$new = array_flip($array); if (!isset($array[false]) && isset($array[true])) { ... there's no false values, and at least one true value }

对于大型数组来说,这可能会变得很昂贵,因此您可以尝试使用array_unique()函数。这将返回一个最多只包含两个值(一个true和一个false)的数组。


好吧,那么上面的方法行不通。我们采用简单的方法:

if (in_array($yourarray, false, TRUE)) {
   ... at least one non-true value
}

afuzzy:是的,但我的PHP 5.3版本仍然会输出“PHP警告:array_flip():只能翻转字符串和整数值!在...”,即使它可以将true/false转换为1/0。 - Marc B

1
使用for循环。如果您想要检查所有变量是否为false,可以使用for循环:一旦找到一个true元素,就可以中断循环,否则变量都是false。如果您想要检查所有变量是否为true,也可以使用相同的方法。

不起作用,因为我需要检查它们是否全部为真,或者全部为假。 - sandy
它会在第一个 true 值后停止并返回 true,但数组也可能有 false 值... - sandy
当然它会在第一个 true 值之后停止。您可以简单地设置一个标志为 false,以指示 for 循环在到达数组结尾之前就已中断了。这样,您就会知道并非所有变量都为 false :) - Manlio

0
// set default value
$result = false;

foreach ($array as $key => $value) {
    if ($value === true) {
        $result = true;
        break;
    } 
}

// $result is now true if any value was true, otherwise it's false

不返回所有都为假的情况。 - GolezTrol
实际上,这会返回如果所有条件都为假,但你说得对,我的解决方案并没有说明是否全部为真 - 我理解为其中之一而不会有中间状态。 - geekuality

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接