PHP 数组比较算法

2022-08-30 23:41:29

在尝试模拟一些PHP行为时,我偶然发现了这个:

    $a=array(0 => 1, 'test' => 2);
    $b=array('test' => 3, 0 => 1);
    var_dump($a==$b, $a>$b, $b>$a);

根据输出大于。在PHP手册中,有一个标准数组比较的转录,它指出数组的值是逐个比较的,如果第二个数组中缺少第一个数组中的键,则数组是不可比较的。目前为止,一切都好。但是,如果我尝试这样做(仅更改第一个元素):var_dump$b$a$a

    $a=array(0 => 2, 'test' => 2);
    $b=array('test' => 3, 0 => 1);
    var_dump($a==$b, $a>$b, $b>$a);

所有三个比较结果均为 。这对我来说看起来是“不可比的”(因为结果与结果相同,而数组也不是,这毫无意义),但这不符合PHP手册的转录。两个键都存在于两个数组中,我预计这次会更大,因为键 0 的内容在 (2 vs. 1) 中更大。false><==$a$a

我试图深入研究PHP源代码,并在 中找到了zend_hash_compare(),但那里的代码似乎像手册中描述的那样工作。zend_hash.c

这是怎么回事?


答案 1

编辑:正如约阿希姆所显示的那样,它处理被调用的订单。借用他的话:“$a>$b在b上循环,首先找到'test'。test'在$b中更大,所以$b更大,它返回false。$b>$a在 a 上循环并首先找到“0”。'0'在$a中更大,所以$a更大,它返回 false。

-- 原文 --

我不是100%确定我是对的;我以前从未见过这个,只是简单地研究了一下(顺便说一句,在一个很好的问题上,主要的荣誉!无论如何,看起来要么是PHP文档是错误的,要么是这是一个错误(在这种情况下,你可能想要提交它),这就是原因:

在 中,似乎对什么是有一些混淆(我正在查看行和,这是我最好的猜测是问题所在,没有做大量的测试)。zend_hash_compare()zend_hash.cordered15141552-1561

这就是我的意思;试试这个:

$a=array(0 => 2, 'test' => 2);
$b=array(0 => 1, 'test' => 3);
var_dump($a==$b, $a>$b, $b>$a);

注意:我只是切换了索引的顺序,并返回.另请参阅以下内容:$a>$btrue

$x=array(0 => 2, 'test' => 2);
$y = $x;
$y[0] = 1; $y['test'] = 3;
var_dump($x==$y, $x>$y, $y>$x);

请注意,此处也返回 true。换句话说,PHP不仅仅是匹配数组键!它关心数组中这些键的顺序!你可以通过在修改之前提出一个“基”数组并将其“复制”到新变量(在我的x /y示例中)来防止这种情况,或者如果你愿意,你可以创建一个对象。$x>$y

换句话说,更简单地说,PHP似乎不仅仅是在关注键值,而是在关注键值和键顺序

再次,我强调我不知道这种预期的行为(如果是的话,这似乎是他们应该在PHP手册中注意到的东西),还是一个错误/错误/等(对我来说似乎更有可能)。但无论哪种方式,我发现它首先通过键数(行在中)进行比较,然后按键值和键顺序进行比较。1496-1501zend_hash.c


答案 2

似乎比较循环是在右手数组上完成>的情况下,在左手数组上完成<的情况下,即总是在所谓的“较小”数组上。元素的顺序很重要,因为转录代码中的 foreach 循环遵循数组顺序。

换句话说;

$a>$b在 b 上循环并首先找到“test”。“test”在$b中更大,所以$b更大,它返回 false。

$b>$a在 a 上循环并首先找到“0”。“0”在$a中更大,因此$a更大,它返回 false。

这实际上是有道理的,然后允许“较大”数组包含“较小”数组没有的元素,并且只要所有公共元素都更大,它们仍然更大。