2012-02-27 52 views
5

首先,我需要提及的是,我深入到手册和PHP文档,并没有找到答案。这里有一个代码,我使用:array_diff_uassoc的行为不明确

class chomik { 

    public $state = 'normal'; 
    public $name = 'no name'; 

    public function __construct($name) { 
     $this->name = $name; 
    } 

    public function __toString() { 
     return $this->name . " - " . $this->state; 
    } 
} 

function compare($a, $b) { 
    echo("$a : $b<br/>"); 
    if($a != $b) { 
     return 0; 
    } 
    else return 1; 
} 

$chomik = new chomik('a'); 
$a = array(5, $chomik, $chomik, $chomik); 
$b = array($chomik, 'b', 'c', 'd'); 
array_diff_uassoc($a, $b, 'compare'); 

我在想什么,array_diff_uassoc将比较这两个数组的所有值,如果值存在,那么将运行键比较。而这个代码的输出是:

1 : 0 
3 : 1 
2 : 1 
3 : 2 
1 : 0 
3 : 1 
2 : 1 
3 : 2 
3 : 3 
3 : 2 
2 : 3 
1 : 3 
0 : 3 

所以首先为什么一些对(1:0或3:1)是重复的?这是否意味着功能忘了它已经比较了这些项目?我认为它会比较所有等值对,但我没有看到它的输出。我错过了什么吗?

所以问题是:根据比较的顺序,这个函数的确切行为是什么,为什么我看到这个重复? (我的PHP版本,如果它可以帮助是:PHP版本5.3.6-13ubuntu3.6)

我真的很困惑,并等待一些很好的解释...

+1

你应该使用严格的比较!== not ==在比较函数中。 – 2012-02-27 00:27:34

+0

在这种情况下,比较本身并不是一件大事。我想知道为什么'echo'在比较时打印这样的结果。并且'echo'在比较之前被触发,所以无论其严格与否都无所谓。 – Karol 2012-02-27 00:33:47

+0

我想要实现的代码是:我只想要这些不在第二个数组中的元素($ a [0]),如果它们在第二个数组中,我希望这些元素具有相同的键(索引)...所以当然函数应该只返回$ a [0] – Karol 2012-03-06 01:18:06

回答

0

op'scomment

我只希望这些元素这不是第二个数组($ A [0])

不能使用array_diff($a, $b);?它返回

array(1) { 
    [0]=> 
    int(5) 
} 

否则,

The documentation指出:

比较函数必须返回一个整数小于,等于或大于零,如果第一个参数是被认为是分别小于,等于或大于第二。

据我了解,这意味着,compare()功能应该更多这样的:

function compare($a, $b) { 
    echo("$a : $b<br/>"); 
    if($a === $b) return 0; 
    else if ($a > $b) return 1; 
    else return -1; 
} 

然而即使有这样的修正,它很奇怪的结果进行比较:

 
1 : 0 
1 : 2 
3 : 1 
2 : 1 
3 : 2 
1 : 0 
1 : 2 
3 : 1 
2 : 1 
3 : 2 
0 : 0 
1 : 0 
1 : 1 
2 : 0 
2 : 1 
2 : 2 
3 : 0 
3 : 1 
3 : 2 
3 : 3 

我询问another question,因为它已经超出了答案的范围。

0

我想你错过了返回值部分。

返回一个数组,其中包含array1中所有不存在于其他数组中的所有条目。

数组键用于比较。

文中缺少的是比较只能联想地完成。这意味着任何自动声明或用户定义的数字键都被键入为不是整数的字符串。

因此,与

$one = array(a,b,c,'hot'=>d); // d has no match and will be returned as array and go to the function alone 
$two = array(a,b,c,d,e,f); // 

因为一个热$ => d不匹配$两个O => d上的缔合水平$一个热=>返回d。

由于字符串和整型数据类型比较的PHP怪癖,用户定义的函数可以用于通过使用更强的比较操作(如===)来增强比较。

这有助于在类型不明确的情况下'0'=> d和0 => d可能看起来很相似,但直到您在代码中这样说。

幸运的是,类型提示是PHP7来摆脱我们这种奇怪的构造和不清楚的文档。

我在我的评论中添加了这个,因为它与您理解哪种php结构最适合您的情况有关。我的评论:

我不这么认为,因为如果($ A = $ B!){在他们的代码是一个 问题。因为他们错误地使用相等的时候,他们应该是 使用相同的运算符!==。他们在为关联密钥设计的 结构中使用数字键。他们可能也 不知道array_udiff哪一个更好地匹配所涉及的数据

+0

这很清楚,op很清楚你在说什么。 – 2015-04-03 14:12:57

+1

我不太确定,因为如果($ a!= $ b){在他们的代码中是一个问题。因为当他们应该使用相同的操作员时,他们错误地使用了平等。他们在为关联密钥设计的结构中使用数字键。他们可能也不知道array_udiff哪一个涉及到的数据更好匹配 – 2015-04-03 16:28:15

0

这确实有点耐人寻味。我在github上查找了最新的PHP源代码(用C++编写,你可能已经知道了),并试图理解它。 (https://github.com/php/php-src/blob/master/ext/standard/array.c

快速搜索我看了有问题的函数声明上线4308

PHP_FUNCTION(array_diff_uassoc) 
{ 
    php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_ASSOC, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_USER); 
} 

所以这表明,实际工作是由php_array_diff函数来完成,可以在同一被发现文件在3938行。它粘贴在这里有点长,265行是确切的,但你可以查看它,如果你想。

这就是我放弃的地步。我无论如何也没有经验,现在已经很晚了,而且我很疲倦地尝试并理解它。我认为首先要进行关键比较,因为比较这些值可能会更高效,但这仅仅是一种猜测。无论如何,他们为什么要这样做可能有一个很好的理由。

所有这一切仅仅是一个长介绍说,你为什么要放一个echocompare函数内部首先array_diff_uassoc的目标是函数的输出。您不应该依赖解析器如何处理它。如果他们明天决定将该C函数的内部运作改为ie。先进行数值比较,你会得到完全不同的结果。

也许你可以使用PHP编写这个替换功能:http://pear.php.net/reference/PHP_Compat-1.6.0a2/__filesource/fsource_PHP_Compat__PHP_Compat-1.6.0a2CompatFunctionarray_diff_uassoc.php.html

可以依靠行为方式不改变,你有内部工作的全面控制......

+0

这是你的github链接的第3631行:'else else if(behavior&INTERSECT_ASSOC && key_compare_type == INTERSECT_COMP_KEY_USER){'。 3321行是一个空行。很明显,回声不是用于功能性的,而是用于测试,而且确实显示出奇怪的结果。 – 2015-04-03 14:05:01

+1

@FélixGagnon-Grenier对不起,我搞砸了那里的行号(我实际上从php.net下载了源代码,后来才发现源代码也在Github上),认为链接更容易,但忘记检查行号Ctrl/Cmd + F会给你带来那里虽然)现在更新,但由于链接指向当前的主人,它可能会在未来再次改变。 – Pevara 2015-04-03 17:17:55

+1

我的答案是,你应该认为这个函数是一个黑盒子,而不是依赖它的内部工作。这些都是关于API和输出,现在*函数如何得到这个结果,因为这可能会在将来发生变化。 – Pevara 2015-04-03 17:21:20