array_udiff 的特殊行为?

问题描述 投票:0回答:3

我有以下 PHP 脚本:

<?php
function filt($k, $l){
    if($k===$l){
        var_dump("valid: ".$k."-".$l);
        return 0;
    }
    return 1;
}
$a6=array(7, 9, 3, 33);
$a7=array(2, 9, 3, 33);
$u=array_udiff($a6, $a7, "filt");
var_dump($u);
?>

输出如下:

string 'valid: 3-3' (length=10)

array
    0 => int 7
    1 => int 9
    3 => int 33

据我所知, array_udiff 应该转储相等的值,只保留第一个数组中不同的值。 这里似乎有什么问题? 我在 Windows 7 上运行 WampServer 版本 2.2。Php 版本:5.3.9。

php arrays
3个回答
4
投票

请注意文档说:

The comparison function must return an integer less than, equal to, or
greater than zero if the first argument is considered to be respectively
less than, equal to, or greater than the second.

你没有这样做。为了确保您这样做,只需让您的

filt
函数返回
$l - $k

对此有一个简单的解释:元素可以按任何顺序排列。为了避免将每个元素与其他元素进行比较,它首先对它们进行排序。这就是为什么你需要 + / 0 / -


3
投票

您没有返回所有必要的值(例如-1、0、1)。请参阅:array_udiff

$a6 = array(7, 9, 3, 33);
$a7 = array(2, 9, 3, 33);

$u = array_udiff($a6, $a7, function ($k, $l){
  return $k > $l ? 1 : ($k < $l ? -1 : 0);
});

print_r($u);

0
投票

不执行三向比较评估可能会破坏 PHP

array_u*()
函数中内置的排序过程。

您可以在运行所有受支持版本的演示中看到,您的特定脚本在以下版本中返回 2 路比较时没有明显的中断:

  • 5.2.6 - 5.2.14,
  • 5.3.0 - 5.3.3,
  • 7.0.0 - 8.3.13

(仅仅因为在现代版本中“它适用于”这个测试用例,并不意味着可以进行懒惰/糟糕的编程。)

但在这些版本中,由于次优返回值的排序,“幕后”的某些内容会受到影响。

  • 5.0.0 - 5.2.5,
  • 5.2.15 - 5.2.17,
  • 5.3.4 - 5.6.40

从PHP7.4开始,可以享受最现代的语法,包括宇宙飞船运算符(三向比较运算符)和箭头函数语法。请注意,因为您的两个数组是平坦的,所以您可以简单地使用

array_diff()
来执行三向比较。 演示

$a6 = [7, 9, 3, 33];
$a7 = [2, 9, 3, 33];

var_dump(array_diff($a6, $a7));

echo "\n---\n";

var_dump(
    array_udiff($a6, $a7, fn($a, $b) => $a <=> $b)
);
© www.soinside.com 2019 - 2024. All rights reserved.