n个变量的排列组合

时间:2014-08-14 13:14:58

标签: php switch-statement cartesian-product

我正在经历一种情况,我需要找到在给定的四个变量中获取空值的可能组合。

让我解释一下:

$之一; $两个; $三样$四日;

我可能会为这些变量获取空值,并且需要对每个案例执行特殊操作。

我在PHP中尝试。

即,

if(($one == '') && ($two == '') && ($three == '') && ($four == '')) {
   //some action
} 
else if (($one == '') && ($two != '') && ($three == '') && ($four == '')) {
  // some action
} else if (($one != '') && ($two == '') && ($three == '') && ($four != '')) {
  // some action
}

。 。

我尝试使用排列公式,但无法完成它。 所以我将有24种组合。任何人都可以为我提供一个简化的解决方案。

提前致谢。

2 个答案:

答案 0 :(得分:0)

您可以通过执行以下操作来减少检查空值的冗余:

$n = ($one == '' ? 0 : 1) + ($two == '' ? 0 : 2) + ($three == '' ? 0 : 4) + ($four == '' ? 0 : 8)

然后使用switch语句检查$n的值,该值介于015之间,用于16种不同的组合。

switch ($n) {
    case 0:
        // case where all four values are ''
        break;
    case 1:
        // case where just $one is not ''
        break;
    case 2:
        // case where just $two is not ''
        break;
    case 3:
        // case where $one and $two are not '' but $three and $four are ''
        break;

    ...

    case 15:
        // case where all four values are not ''
}

答案 1 :(得分:0)

你似乎对这里的组合学感到困惑。

如果你只是检查字符串的某些固定数字 n 是否为空,不管是哪一个,那将是一个组合,并且会有C( 4, n )感兴趣的案例。

如果您对哪些是空的感兴趣,但只有当 n 中的为空时,那将是一个排列,并且会有P(4) , n )感兴趣的案例。

但似乎你对哪些是空的感兴趣,无论有多少。这是一个笛卡尔积,你需要2 ^ 4 = 16个案例。

当你想要枚举这样的东西时,可以把它想象成一个四位二进制数,其中每个数字代表一个变量(按顺序),1表示它不是空的:

  • 0000
  • 0001
  • 0010
  • 0011
  • 0100

因此,对这些可能性的强力线性搜索就像是

//0000
if (($one == '') && ($two == '') && ($three == '') && ($four == '')) {
   //some action
} 
//0001
else if (($one == '') && ($two == '') && ($three == '') && ($four != '')) {
  // some action
}
//0010
else if (($one == '') && ($two == '') && ($three != '') && ($four == '')) {
  // some action
}
//0011
else if (($one == '') && ($two == '') && ($three != '') && ($four != '')) {
  // some action
}
...

但是,由于您实际上是在考虑一系列布尔决策,我建议使用二叉搜索树。这将是一个不那么漂亮的代码,但它是搜索这样的东西最有效的方式(它将需要log_2(16)= 4 if语句,而不是16 - 并且没有逻辑和&&到处理)。

//Is $one empty?
if ($one == '') {

    //Yes, $one is empty. Is $two empty?
    if ($two == '') {

        //Yes, $two is empty. Is $three empty?
        if ($three == '') {

            //Yes, $three is empty. Is $four empty?
            if ($four == '') {
                //Yes, $four is empty. The case is 0000
            } else {
                //No, $four is not empty. The case is 0001
            }

        } else {

            //No, $three is not empty. Is $four empty?
            if ($four == '') {
                //Yes, $four is empty. The case is 0010
            } else {
                //No, $four is not empty. The case is 0011
            }
        }
    } else

        //No, $two is not empty. Is $three empty?
        if ($three == '') {
        ...

现在,这段代码非常有效,但它也非常冗长。如果这些情况中的任何一种行为方式相同,我建议尝试找到一些其他逻辑层次结构,以便在尽可能少的步骤中决定不同的行为 - 但无论如何我建议使用逻辑层次结构< / em>而不是您正在尝试的线性枚举。祝你好运!

修改 潜伏者的建议

$n = ($one == '' ? 0 : 1) + ($two == '' ? 0 : 2) + ($three == '' ? 0 : 4) + ($four == '' ? 0 : 8)

后跟switch语句是一个比上面更清晰的解决方案。我想指出底层逻辑是完全一样的;这行代码实际上构建了我上面描述的二进制数,但是在10中。希望你能看到我的答案和Lurker之间的对应关系,希望我的答案能帮助你理解为什么Lurker的高级代码有效。