【问题标题】:Logic issue in PHPPHP中的逻辑问题
【发布时间】:2011-02-17 18:18:47
【问题描述】:

好的,我测试了下面的内容,我会告诉你我发现了什么:

echo ('-1' < 0) ? 'true' : 'false'; // will echo "true"
echo ('1' > 0) ? 'true' : 'false'; // will echo "true"
# Notice that '-1' and '1' are strings

现在让我们从数据库中获取一个数组,在过滤所有结果后,只获取带有UID = 1 的行。

$this->a = array(
    [0] => array(
        'UID' => '1',
        'PID' => '91',
        'Amount' => '-1'
    ),
    [1] => array(
        'UID' => '1',
        'PID' => '92',
        'Amount' => '1'
    ),
    [2] => array(
        'UID' => '1',
        'PID' => '93',
        'Amount' => '1'
    )
);

现在我想创建一个函数posAmount($PID),如果'Amount' &gt; 0,则返回true,如果'Amount' &lt; 0,则返回false。 (注意:Amount = 0 是我不在乎的东西)。我也想写成类似的函数negAmount($PID),它返回与第一个完全相反的函数。现在,我想向您介绍我的双功能:

public function posAmount($pid)
{
    foreach ($this->a as $a)
    {
        if (count($this->a) == 0) { return false; }
        return ($a['PID'] == $pid and $a['Amount'] > 0) ? true : false;
    }
}

public function negAmount($pid)
{
    foreach ($this->a as $a)
    {

        if (count($this->a) == 0) { return false; }
        return ($a['PID'] == $pid and $a['Amount'] < 0) ? true : false;
    }
}

很酷的事实是,关于第一个数组(我检查了 var_dump() 在整个脚本中保持其性质):

$istance->negAmount(91); // Returns true, as expected
$istance->posAmount(92); // Returns false, as NOT expected.
# Why do God wants me to get mad?

【问题讨论】:

  • 必须是这一行:if (count($this-&gt;votes) == 0) { return false; }
  • return ($a['PID'] == $pid and $a['Amount'] &lt; 0) ? true : false 可以写成return ($a['PID'] == $pid and $a['Amount'] &lt; 0),为什么在每个循环迭代中都调用if (count($this-&gt;votes) == 0) { return false; }?这是一种不好的做法。
  • @BoltClock,不,这是一个错字。很抱歉。
  • 您刚刚发现了为什么弱和动态(它们是分开的,我知道,但两者都在这里发挥作用)打字会很糟糕的一个原因;)
  • 感谢您纠正错字。我更新了我的答案以包含工作代码和解释。

标签: php logic


【解决方案1】:

问题是您总是在 foreach 循环的第一次迭代中返回。你应该像这样重写函数:

public function negAmount($pid) {
    if (count($this->a) == 0) { return false; }
    foreach ($this->a as $a) {
        if ($a['PID'] == $pid) {
            if ($a['Amount'] < 0) {
                return true;
            }
        }
    }
    return false;
}

public function posAmount($pid) {
    if (count($this->a) == 0) { return false; }
    foreach ($this->a as $a) {
        if ($a['PID'] == $pid) {
            if ($a['Amount'] > 0) {
                return true;
            }
        }
    }
    return false;
}

【讨论】:

  • 天啊,我想我他妈的爱你。严重地。那太愚蠢了。非常感谢。你节省了我至少 3 个小时的生命。谢谢谢谢谢谢。 (将在 3 分钟内接受此作为答案)
  • 这个函数会在适当的数组值已经被检查之后继续循环,然后返回 false。如果数据量很小,这不会有太大区别,但是对于大型数据集,这可能会带来很大的性能问题。在 PID 匹配时做三元运算符并在找到匹配时立即返回 true 或 false 更有效。
  • @Chris 大问题? PHP 可以在眨眼之间执行数万个 foreach-loops(显然不是经验数据,但相对准确)。
  • 这是你的答案。您需要首先测试 PID 是否匹配,然后测试 Amount。现在你测试 0 计数,然后在第一个数组索引上返回 true false,退出函数。
  • 尽管如此,当您可以返回一个值或调用break 以在循环目的已达到时停止循环时,不必要地遍历数组是不好的做法。当您可以通过更好的逻辑完全避免问题时,为什么还要编写其中包含潜在炸弹的代码?
【解决方案2】:

可能只是您的演示代码中的拼写错误,但 posAmount 方法是循环 $this-&gt;a,而另一个是循环 $this-&gt;votes - OP 已更正

您的代码中有一些奇怪的东西。为什么要从foreach 循环中检查$this-&gt;a 的计数?在开始循环之前检查计数会更有意义。

此外,您的比较中存在一些逻辑错误。您只是在循环中比较第一次迭代......它会为数组的第一个索引返回 true 或 false,甚至从不查看其他索引。在比较 - 并返回 - 任何东西之前,您需要匹配循环中的 PID。像这样:

public function posAmount($pid)
{
    if (count($this->a) == 0) { return false; }
    foreach ($this->votes as $a) {
        if ($a['PID'] == $pid)
        return $a['Amount'] > 0 ? true : false;
    }
    return false;
}

public function posAmount($pid)
{
    if (count($this->a) == 0) { return false; }
    foreach ($this->votes as $a) {
        if ($a['PID'] == $pid)
        return $a['Amount'] < 0 ? true : false;
    }
    return false;
}

【讨论】:

  • +1 进行解释,但接受的答案是@Stephen,他首先得到它。
  • return $a['Amount'] &lt; 0 ? true : false; 是多余的。只需使用return $a['Amount'] &lt; 0;
  • 适当地注意到和承认,但是,为了清晰的意图,我更喜欢使用三元。
【解决方案3】:

问题是您尝试将字符串与 int 进行比较,而不尝试转换它。将$a['Amount'] 更改为(int)$a['Amount'] 看看会发生什么。

【讨论】:

  • 如最顶部的sn-p所示,PHP不会自动进行类型转换。
  • PHP 的松散类型在这种比较之前不需要强制转换——类型不是这里的问题。
  • 试过了,但没有任何改变。无论如何,即使使用字符串,它也应该可以工作(见第一行)。
【解决方案4】:

所以在这里你迭代 $this->a:

public function posAmount($pid)
{
    foreach ($this->a as $a)

但是这里是 $this->votes:

public function posAmount($pid)
{
    foreach ($this->a as $a)

错别字什么的……

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-15
    • 2018-12-08
    • 1970-01-01
    相关资源
    最近更新 更多