array_udiff 好像不行

array_udiff seems not work

我正在尝试将两个数组与 array_udiff 进行比较,但这很奇怪。似乎 array_udiff 没有得到正确答案。这里是live demo。结果应该是一个空数组,但保留一个元素未过滤掉。

<?php

$string = '{
  "sakiniai": [

      {
        "Faktas": "A",
        "value": "true"
      },
      {
        "Faktas": "B",
        "value": "true"
      },
      {
        "Faktas": "A",
        "value": "false"
      }
  ]
}';

$sakiniais = json_decode($string, true)['sakiniai'];


$v = $sakiniais[0];
$arr[] = $v;
$v['value'] = $v['value'] == "true" ? "false" : "true";
$arr[] = $v;
var_dump($arr);
var_dump($sakiniais);


print_r(array_udiff($arr, $sakiniais, function($a, $b){
/*
var_dump($a);
var_dump($b);
var_dump($a == $b);
echo "\n\n\n";
*/
return $a == $b ? 0 : -1;}
));

输出

    array(2) {
  [0]=>
  array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(4) "true"
  }
  [1]=>
  array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(5) "false"
  }
}
array(3) {
  [0]=>
  array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(4) "true"
  }
  [1]=>
  array(2) {
    ["Faktas"]=>
    string(1) "B"
    ["value"]=>
    string(4) "true"
  }
  [2]=>
  array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(5) "false"
  }
}
Array
(
    [1] => Array
        (
            [Faktas] => A
            [value] => false
        )

)

没什么奇怪的,一切都按预期进行。看一下数组比较:

$arraysAreEqual = ($a == $b); // TRUE if $a and $b have the same key/value pairs.
$arraysAreEqual = ($a === $b); // TRUE if $a and $b have the same key/value pairs in the same order and of the same types.

所以,$arr[0] == $sakiniai[0] 为真,但 $arr[1] == $sakiniai[2] 为假,输出为 $arr[1]

$arr

array(2) {
  [0]=>
  array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(4) "true"
  }
  [1]=>
  array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(5) "false"
  }
}

$sakiniai

array(3) {
  [0]=>
  array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(4) "true"
  }
  [1]=>
  array(2) {
    ["Faktas"]=>
    string(1) "B"
    ["value"]=>
    string(4) "true"
  }
  [2]=>
  array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(5) "false"
  }
}

结果

Array
(
    [1] => Array
        (
            [Faktas] => A
            [value] => false
        )

)

问题是 array_udiff 没有对所有值进行比较,这似乎是由您的比较函数引起的。

array_udiff() 期望可调用函数是一个真正的比较函数,但您 returning 总是 0 和 -1,但从不为 1。

在完成它的工作之前,array_udiff() 尝试对两个数组进行排序并删除重复项。如果它不能依赖你的比较函数,它就不能执行所有需要的比较,有些值是 "jumped"。

查看 the documentation 中的所有评论,特别是 napcoder 评论

Note that the compare function is used also internally, to order the arrays and choose which element compare against in the next round.

If your compare function is not really comparing (ie. returns 0 if elements are equals, 1 otherwise), you will receive an unexpected result.

这是通过查看您的数组来演示的

$arr

array(2) {
  [0]=>
  array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(4) "true"
  }
  [1]=>
  array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(5) "false"
  }
}

和$sakiniais

array(3) {
  [0]=>
  array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(4) "true"
  }
  [1]=>
  array(2) {
    ["Faktas"]=>
    string(1) "B"
    ["value"]=>
    string(4) "true"
  }
  [2]=>
  array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(5) "false"
  }
}

您应该期望测试两个数组之间的所有组合,但测试的组合(下方)不包括 A-False 与 A-False

array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(4) "true"
}
array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(5) "false"
}
bool(false)



array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(4) "true"
}
array(2) {
    ["Faktas"]=>
    string(1) "B"
    ["value"]=>
    string(4) "true"
}
bool(false)



array(2) {
    ["Faktas"]=>
    string(1) "B"
    ["value"]=>
    string(4) "true"
}
array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(5) "false"
}
bool(false)



array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(4) "true"
}
array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(4) "true"
}
bool(true)



array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(4) "true"
}
array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(5) "false"
}
bool(false)



array(2) {
    ["Faktas"]=>
    string(1) "A"
    ["value"]=>
    string(5) "false"
}
array(2) {
    ["Faktas"]=>
    string(1) "B"
    ["value"]=>
    string(4) "true"
}
bool(false)

this post 的正确答案中,还有一些关于 array_udiff 工作原理的其他有用见解

您可以像这样更改您的 return 语句

if ($a < $b) {
    return -1;
} elseif ($a > $b) {
    return 1;
} else {
    return 0;
}

(如果您想知道如何比较两个数组的 less/greater,请查看 this link 部分中的 "Comparison with Various Types" 和 "Example #2 Transcription of standard array comparison" 示例)