array_diff

(PHP 4 >= 4.0.1, PHP 5, PHP 7, PHP 8)

array_diff计算数组的差集

描述

array_diff(array $array, array ...$arrays): array

比较 array 与一个或多个其他数组,并返回 array 中不在其他任何数组中的值。

参数

array

要比较的数组

arrays

要比较的数组

返回值

返回一个 array,其中包含 array 中不在任何其他数组中的所有条目。 array 数组中的键被保留。

变更日志

版本 描述
8.0.0 此函数现在可以只用一个参数调用。以前,至少需要两个参数。

示例

示例 #1 array_diff() 示例

<?php
$array1
= array("a" => "green", "red", "blue", "red");
$array2 = array("b" => "green", "yellow", "red");
$result = array_diff($array1, $array2);

print_r($result);
?>

$array1 中的多个出现都被视为相同。这将输出

Array
(
    [1] => blue
)

示例 #2 array_diff() 与不匹配类型的示例

只有当 (string) $elem1 === (string) $elem2 时,两个元素才被认为相等。也就是说,当 字符串表示 相同时。

<?php
// 这将生成一个 Notice,指出数组不能转换为字符串。
$source = [1, 2, 3, 4];
$filter = [3, 4, [5], 6];
$result = array_diff($source, $filter);

// 而这没问题,因为对象可以转换为字符串。
class S {
private
$v;

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

public function
__toString() {
return
$this->v;
}
}

$source = [new S('a'), new S('b'), new S('c')];
$filter = [new S('b'), new S('c'), new S('d')];

$result = array_diff($source, $filter);

// $result 现在包含一个 S('a') 的实例;
?>

要使用备用比较函数,请参阅 array_udiff()

备注

注意:

此函数仅检查 n 维数组的一维。当然,你可以使用 array_diff($array1[0], $array2[0]); 检查更深的维度。

参见

添加注释

用户贡献的注释 29 个注释

nilsandre at gmx dot de
17 年前
同样,函数的描述现在具有误导性。我寻找一个函数,它(数学上)计算 A - B,或者,用另一种方式写,A \ B。或者,换句话说,假设

A := {a1, ..., an} 和 B:= {a1, b1, ... , bm}

=> array_diff(A,B) = {a2, ..., an}

array_diff(A,B) 返回 A 中所有不是 B 的元素的元素 (= A 除去 B)。

我认为您应该更精确地在文档中包含这一点。
匿名
18 年前
array_diff 提供了一种便捷的方式,可以通过值删除数组元素,而无需通过冗长的 foreach 循环 unset 它们,然后重新对数组进行索引。

<?php

// 传递要删除的值和要从中删除的数组
function array_delete( $value, $array)
{
$array = array_diff( $array, array($value) );
return
$array;
}
?>
james dot PLZNOSPAM at bush dot cc
7 年前
如果你想用一种简单的方式来显示存在于任何一个数组中但不存在于两个数组中的值,你可以使用这个

<?php
function arrayDiff($A, $B) {
$intersect = array_intersect($A, $B);
return
array_merge(array_diff($A, $intersect), array_diff($B, $intersect));
}
?>

如果您想考虑键,请使用 array_diff_assoc();如果您想删除空值,请使用 array_filter()。
wes dot melton at gmail dot com
7 年前
需要注意的是,array_diff() 在处理大型数组时,既不是快速函数,也不是内存效率高的函数。

根据我的经验,当我发现自己对大型数组(50+ k/v/对)运行 array_diff() 时,我几乎总是意识到自己正在从错误的角度解决问题。

通常情况下,在重新处理问题以避免使用 array_diff() 时,尤其是在处理更大的数据集时,我发现性能有了显著提高,并且得到了优化。
Al Amin Chayan (mail at chayan dot me)
3 年前
<?php
/**
* 检查一个数组是否为另一个数组的子集
*
* @param array $subset
* @param array $set
* @return bool
*/
function is_subset(array $subset, array $set): bool {
return (bool)!
array_diff($subset, $set);
}

$u = [1, 5, 6, 8, 10];
$a = [1, 5];
$b = [6, 7];

var_dump(is_subset($a, $u)); // true
var_dump(is_subset($b, $u)); // false
Jeppe Utzon
11 年前
如果您只需要知道两个数组的值是否完全相同(不考虑键和顺序),那么可以使用以下简单方法,而不是使用 array_diff

<?php

function identical_values( $arrayA , $arrayB ) {

sort( $arrayA );
sort( $arrayB );

return
$arrayA == $arrayB;
}

// 示例:

$array1 = array( "red" , "green" , "blue" );
$array2 = array( "green" , "red" , "blue" );
$array3 = array( "red" , "green" , "blue" , "yellow" );
$array4 = array( "red" , "yellow" , "blue" );
$array5 = array( "x" => "red" , "y" => "green" , "z" => "blue" );

identical_values( $array1 , $array2 ); // true
identical_values( $array1 , $array3 ); // false
identical_values( $array1 , $array4 ); // false
identical_values( $array1 , $array5 ); // true

?>

该函数仅在两个数组包含相同数量的值,并且一个数组中的每个值在另一个数组中都有一个完全相同的副本时返回 true。其他情况都将返回 false。

我用于评估两个数组是否包含(全部)相同值的替代方法

<?php

sort
($a); $sort(b); return $a == $b;

?>

可能比这种 array_diff 方法稍微快一点(10-20%)

<?php

return ( count( $a ) == count( $b ) && !array_diff( $a , $b ) ? true : false );

?>

但只有在两个数组包含相同数量的值时,而且只在某些情况下才会更快。否则,由于使用了 count() 测试,在 array_diff() 之前,后者方法将快得多。

此外,如果两个数组包含不同数量的值,那么哪种方法更快将取决于是否需要对两个数组进行排序。两次 sort() 比一次 array_diff() 稍微慢一些,但是如果其中一个数组已经排序,那么您只需要对另一个数组进行排序,这将比 array_diff() 快近两倍。

基本上:2 次 sort() 比 1 次 array_diff() 慢,1 次 array_diff() 比 1 次 sort() 慢。
firegun at terra dot com dot br
15 年前
大家好,

我一直在寻找一个适用于递归数组的 array_diff,我尝试过 ottodenn at gmail dot com 函数,但它并没有按预期在我的案例中工作,所以我创建了自己的函数。我还没有对它进行过广泛的测试,但我会解释我的场景,而且这个函数在这个场景中运行得很好:D

我们有以下两个数组:

<?php
$aArray1
['marcie'] = array('banana' => 1, 'orange' => 1, 'pasta' => 1);
$aArray1['kenji'] = array('apple' => 1, 'pie' => 1, 'pasta' => 1);

$aArray2['marcie'] = array('banana' => 1, 'orange' => 1);
?>

与 array_diff 一样,该函数返回 aArray1 中所有存在于 aArray2 中的项,因此我们期望的结果是

<?php
$aDiff
['marcie'] = array('pasta' => 1);
$aDiff['kenji'] = array('apple' => 1, 'pie' => 1, 'pasta' => 1);
?>

现在关于该函数的一些评论:
- 与 PHP 的 array_diff 不同,该函数不使用 === 运算符,而是使用 ==,因此 0 等于 '0' 或 false,但这可以更改,不会造成影响。
- 该函数检查数组的键,而 array_diff 仅比较值。

我真的很希望这能帮助到某些人,就像我从其他用户那里获得帮助一样。(请务必仔细检查它是否适用于您的情况,就像我所说的,我只测试了类似于我展示的场景)

<?php
function arrayRecursiveDiff($aArray1, $aArray2) {
$aReturn = array();

foreach (
$aArray1 as $mKey => $mValue) {
if (
array_key_exists($mKey, $aArray2)) {
if (
is_array($mValue)) {
$aRecursiveDiff = arrayRecursiveDiff($mValue, $aArray2[$mKey]);
if (
count($aRecursiveDiff)) { $aReturn[$mKey] = $aRecursiveDiff; }
} else {
if (
$mValue != $aArray2[$mKey]) {
$aReturn[$mKey] = $mValue;
}
}
} else {
$aReturn[$mKey] = $mValue;
}
}

return
$aReturn;
}
?>
SeanECoates at !donotspam!yahoo dot ca
22 年前
我刚刚发现 `array_diff()` 的一个非常实用的用途。在读取目录(`opendir`、`readdir`)时,我几乎不希望 `"."` 或 `".."` 存在于我创建的文件数组中。以下是一个简单的方法来删除它们。

<?php
$someFiles
= array();
$dp = opendir("/some/dir");
while(
$someFiles[] = readdir($dp));
closedir($dp);

$removeDirs = array(".","..");
$someFiles = array_diff($someFiles, $removeDirs);

foreach(
$someFiles AS $thisFile) echo $thisFile."\n";
?>

S
Prakashgun
6 years ago
如果第一个数组中出现重复值,它也会被包含。在输出中,"blue" 出现了两次。

<?php

$array1
= array("a" => "green", "red", "blue", "red", "blue");
$array2 = array("b" => "green", "yellow", "red");
$result = array_diff($array1, $array2);

print_r($result);

//Output
//Array ( [1] => blue [3] => blue )
merlyn dot tgz at gmail dot com
12 years ago
`array_diff` 有更快的实现方式,但有一些限制。如果您需要比较两个整数或字符串数组,可以使用以下函数

public static function arrayDiffEmulation($arrayFrom, $arrayAgainst)
{
$arrayAgainst = array_flip($arrayAgainst);

foreach ($arrayFrom as $key => $value) {
if(isset($arrayAgainst[$value])) {
unset($arrayFrom[$key]);
}
}

return $arrayFrom;
}

它比 `array_diff` 快大约 10 倍。

php > $t = microtime(true);$a = range(0,25000); $b = range(15000,500000); $c = array_diff($a, $b);echo microtime(true) - $t;
4.4335179328918
php > $t = microtime(true);$a = range(0,25000); $b = range(15000,500000); $c = arrayDiffEmulation($a, $b);echo microtime(true) - $t;
0.37219095230103
Anonymous
9 years ago
我一直想要类似这样的功能,以避免在项目目录中列出所有要排除的文件和文件夹。

function array_preg_diff($a, $p) {
foreach ($a as $i => $v)
if (preg_match($p, $v))
unset($a[$i]);
return $a;
}

$relevantFiles = array_preg_diff(scandir('somedir'), '/^\./');

而不是

$relevantFiles = array_diff(scandir('somedir'), array('.', '..', '.idea', '.project));
merlinyoda at dorproject dot net
16 years ago
正如 `kitchin` 在 2007 年 6 月 19 日 03:49 的评论中所述,以及 `nilsandre at gmx dot de` 在 2007 年 7 月 17 日 10:45 的评论中所述,如果您没有从集合论的角度思考,`array_diff` 的行为可能不直观。

`array_diff()` 返回数组 A 中存在的元素与数组 B 中存在的元素的 *数学* 差值(也称为减法),*而不是* 数组之间不同的元素(即那些存在于 A 或 B 中,但不在 A 和 B 中的元素)。

绘制一个韦恩图或欧拉图可能有助于可视化...

对于返回您可能期望的值的函数,以下是一个

<?php
function array_xor ($array_a, $array_b) {
$union_array = array_merge($array_a, $array_b);
$intersect_array = array_intersect($array_a, $array_b);
return
array_diff($union_array, $intersect_array)
}
?>
Simon Riget at paragi.dk
18 年前
一个简单的多维键感知 `array_diff` 函数。

<?php
function arr_diff($a1,$a2){
foreach(
$a1 as $k=>$v){
unset(
$dv);
if(
is_int($k)){
// Compare values
if(array_search($v,$a2)===false) $dv=$v;
else if(
is_array($v)) $dv=arr_diff($v,$a2[$k]);
if(
$dv) $diff[]=$dv;
}else{
// Compare noninteger keys
if(!$a2[$k]) $dv=$v;
else if(
is_array($v)) $dv=arr_diff($v,$a2[$k]);
if(
$dv) $diff[$k]=$dv;
}
}
return
$diff;
}
?>

此函数满足我的当前需求,但我相信它可以改进。
Tim Trefren
16 years ago
以下是一个针对 `array_diff` 的小型包装器 - 我发现自己需要迭代编辑后的数组,并且不需要原始键用于任何操作。

<?php
function arrayDiff($array1, $array2){
# 此 `array_diff` 包装器重新键入返回的数组
$valid_array = array_diff($array1,$array2);

# 重新实例化 `$array1` 变量
$array1 = array();

# 循环遍历验证后的数组并将元素移动到 `$array1`
# 这是必要的,因为 `array_diff` 函数返回保留其原始键的数组
foreach ($valid_array as $valid){
$array1[] = $valid;
}
return
$array1;
}
?>
Anonymous
20 years ago
从页面
注意:请注意,此函数只检查 n 维数组的一维。当然,您可以通过使用 `array_diff($array1[0], $array2[0]);` 来检查更深层的维度。

我找到了一个绕过此问题的方法。我有两个由数组组成的数组。
我想从第一个数组中提取所有不在第二个数组中的数组。所以,我使用了 `serialize()` 函数。

<?php
function my_serialize(&$arr,$pos){
$arr = serialize($arr);
}

function
my_unserialize(&$arr,$pos){
$arr = unserialize($arr);
}

// 创建一个副本
$first_array_s = $first_array;
$second_array_s = $second_array;

// 对所有子数组进行序列化
array_walk($first_array_s,'my_serialize');
array_walk($second_array_s,'my_serialize');

// 对序列化后的版本进行 `array_diff`
$diff = array_diff($first_array_s,$second_array_s);

// 反序列化结果
array_walk($diff,'my_unserialize');

// 你得到了它!
print_r($diff);
?>
emeka dot echeruo at gmail dot com
8 years ago
重新提交... 此更新考虑了比较问题
计算所有数组的差值
<?php

/**
* array_diffs — 计算所有数组的差异
*
* @param array
*
* array1 - 要比较的数组,也是比较的基准
* array2 - 要比较的数组,也是比较的基准
* array(n) - 更多要比较的数组,也是比较的基准
*
* @return array 返回所有包含在任何数组中都无法匹配的条目的数组。
*/

function array_diffs() {
$count = func_num_args();
if(
$count < 2) {
trigger_error('比较至少需要提供 2 个数组。');
}
$check = array();
$out = array();
// 解决比较问题
$func = function($a, $b) {
$dbl = function($i, $d) {
$e = 0.00001;
if(
abs($i-$d) < $e) {
return
true;
}
return
false;
};
if((
gettype($a) == 'integer' && gettype($b['value']) == 'double') || (gettype($a) == 'double' && gettype($b['value']) == 'integer')) {
if((
gettype($a) == 'integer' && $dbl((double) $a, $b['value'])) || (gettype($b['value']) == 'integer' && $dbl((double) $b['value'], $a))) {
return
true;
}
} elseif((
gettype($a) == 'double') && (gettype($b['value']) == 'double')) {
return
$dbl($a,$b['value']);
} elseif(
$a == $b['value']) {
return
true;
}
return
false;
};
for(
$i = 0; $i < $count; $i++) {
if(!
is_array(func_get_arg($i))) {
trigger_error('参数必须以数组形式传递。');
}
foreach(
func_get_arg($i) as $key => $value) {
if(
is_numeric($key) && is_string($value)) {
if(
array_key_exists($value, $check) && $func($value, $check[$value])) {
$check[$value]['count'] = $check[$value]['count'] + 1;
} else {
$check[$value]['value'] = $value;
$check[$value]['count'] = 1;
}
} elseif(
is_numeric($key) && (is_bool($value) || is_null($value) || is_numeric($value) || is_object($value) || is_resource($value))) {
$update = false;
foreach(
$check as $check_key => $check_value) {
if(
is_numeric($key) && (is_bool($check_value['value']) || is_null($check_value['value']) || is_numeric($check_value['value']) || is_object($check_value['value']) || is_resource($check_value['value'])) && $func($value, $check_value)) {
$update = true;
$check[$check_key]['count'] = $check[$check_key]['count'] + 1;
}
}
if(!
$update) {
$check[] = array('value' => $value, 'count' => 1);
}
} else {
if(
array_key_exists($key, $check) && $func($value, $check[$key])) {
$check[$key]['count'] = $check[$key]['count'] + 1;
} else {
$check[$key]['value'] = $value;
$check[$key]['count'] = 1;
}
}
}
}
foreach(
$check as $check_key => $check_value) {
if(
$check_value['count'] == 1) {
for (
$i = 0; $i < $count; $i++) {
foreach(
func_get_arg($i) as $key => $value) {
if(
is_numeric($key) && is_string($value) && ($value == (string) $check_key)) {
$out[$i][$key] = $value;
} elseif(
is_numeric($key) && ($check_value['value'] == $value)) {
$out[$i][$key] = $value;
} elseif(
is_string($key) && ($check_value['value'] == $value)) {
$out[$i][$key] = $value;
}
}
}
}
}
return
$out;
}

?>
vojtech dot hordejcuk at gmail dot com
14 年前
基于一位朋友的代码,我创建了以下函数来创建类似 HTML diff 的内容。我希望它能有所帮助。

<?php
private function diff ($old, $new)
{
$old = preg_replace ('/ +/', ' ', $old);
$new = preg_replace ('/ +/', ' ', $new);

$lo = explode ("\n", trim ($old) . "\n");
$ln = explode ("\n", trim ($new) . "\n");
$size = max (count ($lo), count ($ln));

$equ = array_intersect ($lo, $ln);
$ins = array_diff ($ln, $lo);
$del = array_diff ($lo, $ln);

$out = '';

for (
$i = 0; $i < $size; $i++)
{
if (isset (
$del [$i]))
{
$out .= '<p><del>' . $del [$i] . '</del></p>';
}

if (isset (
$equ [$i]))
{
$out .= '<p>' . $equ [$i] . '</p>';
}

if (isset (
$ins [$i]))
{
$out .= '<p><ins>' . $ins [$i] . '</ins></p>';
}
}

return
$out;
}
?>
emeka at echeruo at gmail dot com
8 years ago
重新提交... 此更新考虑了比较问题

计算所有数组的差值

<?php

/**
* array_diffs — Computes the difference of all the arrays
*
* @param array
*
* array1 - The array to compare from and against
* array2 - The array to compare from and against
* array(n) - More arrays to compare from and against
*
* @return array Returns all the arrays that do contains entries that cannot be matched in any of the arrays.
*/

function array_diffs() {
$count = func_num_args();
if(
$count < 2) {
trigger_error('Must provide at least 2 arrays for comparison.');
}
$check = array();
$out = array();
//resolve comparison issues in PHP
$func = function($a, $b) {
if(
gettype($a) == 'integer' && gettype($b['value']) == 'double' || gettype($a) == 'double' && gettype($b['value']) == 'integer') {
if(
gettype($a) == 'integer') {
if((double)
$a == $b['value']) {
return
true;
}
} else {
if((double)
$b['value'] == $a) {
return
true;
}
}
} elseif(
gettype($a) == 'double' && gettype($b['value']) == 'double') {
$epsilon = 0.00001;
if(
abs($a - $b['value']) < $epsilon) {
return
true;
}
} else {
if(
$a == $b['value']) {
return
true;
}
}
return
false;
};
for (
$i = 0; $i < $count; $i++) {
if(!
is_array(func_get_arg($i))) {
trigger_error('Parameters must be passed as arrays.');
}
foreach(
func_get_arg($i) as $key => $value) {
if(
is_numeric($key) && is_string($value)) {
if(
array_key_exists($value, $check) && $func($value, $check[$value])) {
$check[$value]['count'] = $check[$value]['count'] + 1;
} else {
$check[$value]['value'] = $value;
$check[$value]['count'] = 1;
}
} elseif(
is_numeric($key) && (is_bool($value) || is_null($value) || is_numeric($value) || is_object($value) || is_resource($value))) {
$update = false;
foreach(
$check as $check_key => $check_value) {
if(
is_numeric($key) && (is_bool($check_value['value']) || is_null($check_value['value']) || is_numeric($check_value['value']) || is_object($check_value['value']) || is_resource($check_value['value']))) {
if(
$func($value, $check_value)) {
$update = true;
$check[$check_key]['count'] = $check[$check_key]['count'] + 1;
}
}
}
if(!
$update) {
$check[] = array('value' => $value, 'count' => 1);
}
} else {
if(
array_key_exists($key, $check) && $func($value, $check[$key])) {
$check[$key]['count'] = $check[$key]['count'] + 1;
} else {
$check[$key]['value'] = $value;
$check[$key]['count'] = 1;
}
}
}
}
foreach(
$check as $check_key => $check_value) {
if(
$check_value['count'] == 1) {
for (
$i = 0; $i < $count; $i++) {
foreach(
func_get_arg($i) as $key => $value) {
if(
is_numeric($key) && is_string($value)) {
if(
$value == (string) $check_key) {
$out[$i][$key] = $value;
}
} elseif(
is_numeric($key) && (is_bool($value) || is_null($value) || is_numeric($value) || is_object($value) || is_resource($value))) {
if(
is_numeric($key) && (is_bool($check_value['value']) || is_null($check_value['value']) || is_numeric($check_value['value']) || is_object($check_value['value']) || is_resource($check_value['value']))) {
if(
$check_value['value'] == $value) {
$out[$i][$key] = $value;
}
}
} else {
if(
$key == $check_key) {
$out[$i][$key] = $value;
}
}
}
}
}
}
return
$out;
}

?>
javierchinapequeno at yahoo dot es
13 年前
您好,我想给所有需要使用此函数比较两个包含大量元素的数组的人一些建议。 您应该先对两个数组进行排序,然后再进行比较,这样会更快。
谢谢
wrey75 at gmail dot com
9 years ago
差异仅在第一层产生。 如果您想比较 2 个数组,您可以使用以下链接中的代码:https://gist.github.com/wrey75/c631f6fe9c975354aec7 (包括一个带有修补数组功能的类)。

以下是基本函数

function my_array_diff($arr1, $arr2) {
$diff = array();

// 检查相似之处
foreach( $arr1 as $k1=>$v1 ){
if( isset( $arr2[$k1]) ){
$v2 = $arr2[$k1];
if( is_array($v1) && is_array($v2) ){
// 2 个数组:继续深入...
// .. 并说明它是一个更新!
$changes = self::diff($v1, $v2);
if( count($changes) > 0 ){
// 如果没有更改,则忽略
$diff[$k1] = array('upd' => $changes);
}
unset($arr2[$k1]); // 不要忘记
}
else if( $v2 === $v1 ){
// 取消第二个数组上的值
// 用于“剩余”
unset( $arr2[$k1] );
}
else {
// 不管是数组还是其他
$diff[$k1] = array( 'old' => $v1, 'new'=>$v2 );
unset( $arr2[$k1] );
}
}
else {
// 删除信息
$diff[$k1] = array( 'old' => $v1 );
}
}

// 现在,检查 $arr2 中的新内容
reset( $arr2 ); // 不要争论它是多余的(即使我相信你)
foreach( $arr2 as $k=>$v ){
// 好吧,它对你来说相当愚蠢,我的朋友
$diff[$k] = array( 'new' => $v );
}
return $diff;
}
gilthans at NOgmailSPAM dot com
17 年前
我需要一个函数来只删除元素在第二个数组中出现的次数。 换句话说,如果你有数组(1,1,2)和数组(1),则返回值应该是数组(1,2)。
所以我在这里构建了这个函数

<?php
function array_diff_once(){
if((
$args = func_num_args()) < 2)
return
false;
$arr1 = func_get_arg(0);
$arr2 = func_get_arg(1);
if(!
is_array($arr1) || !is_array($arr2))
return
false;
foreach(
$arr2 as $remove){
foreach(
$arr1 as $k=>$v){
if((string)
$v === (string)$remove){ //NOTE: 如果你需要严格的差异,请移除两个 '(string)'
unset($arr1[$k]);
break;
// 这几乎是与真正的 array_diff 的唯一区别 :P
}
}
}
// 处理多个参数
$c = $args;
while(
$c > 2){
$c--;
$arr1 = array_diff_once($arr1, func_get_arg($args-$c+1));
}
return
$arr1;
}
$arr1 = Array("blue", "four"=>4, "color"=>"red", "blue", "green", "green", "name"=>"jon", "green");
$arr2 = Array("4", "red", "blue", "green");
print_r(array_diff_once($arr1, $arr2));
?>
这将打印
Array ( [1] => blue [3] => green [name] => jon [4] => green )

注意,它从左到右删除元素,与您可能预期的相反; 在我的情况下,元素的顺序没有关系。 纠正它需要一个小的变动。
匿名
14 年前
嗨!
我尽力寻找我将在这里解释的问题的解决方案,在阅读了所有数组函数和可能性之后,我不得不创建我认为应该在下一个 PHP 版本中存在的解决方案。

我需要的是某种差异,但它使用两个数组并在同一时间修改它们,而不是返回一个包含差异本身的数组作为结果。

所以,举个例子

A = 1,2,3
B = 2,3,4

不应该为

C = 1,4

而是

A = 1
B = 4

所以基本上,我想删除两个数组中的重合部分。

现在,我有一些操作要执行,我知道要对来自一个数组或另一个数组的值执行哪些操作。
使用正常的 DIFF 我无法做到,因为如果我有一个像 C=1,4 这样的数组,我不知道我是否应该对 1 或 4 执行 Action_A,但我确实知道 A 中的所有内容都将进入 Action_A,B 中的所有内容都将进入 Action_B。 所以 4 也是一样的,不知道要应用哪个操作...

所以我创建了这个

<?php
function array_diff_ORG_NEW(&$org, &$new, $type='VALUES'){
switch(
$type){
case
'VALUES':
$int = array_values(array_intersect($org, $new)); //C = A ^ B
$org = array_values(array_diff($org, $int)); //A' = A - C
$new= array_values(array_diff($new, $int)); //B' = B - C
break;
case
'KEYS':
$int = array_values(array_intersect_key($org, $new)); //C = A ^ B
$org = array_values(array_diff_key($org, $int)); //A' = A - C
$new= array_values(array_diff_key($new, $int)); //B' = B - C
break;
}
}
?>

这个代码非常巧妙,通过引用进行操作,并修改数组,删除两者的重合部分,保留非重合部分。

所以调用这个函数的代码类似这样:

<?php
$original
= array(1,2,3);
$new = array(2,3,4);

array_diff_ORG_NEW($original, $new, 'VALUES');
?>

然后,我的数组就会变成我想要的样子。

$original = 1
$new = 4

现在,我为什么精确地使用它呢?

想象一下,你有一些 "事件",以及一些你创建事件时选定的用户,这些用户可以 "看到" 你创建的事件。所以你把这个事件 "分享" 给一些用户。明白了吗?

想象一下,你创建了事件_A,并与用户 1、2、3 共享。

现在你想修改这个事件,你决定修改与它共享的用户。想象一下,你把它改为与用户 2、3、4 共享。

(数字是用户 ID)。

所以,在修改时,你可以管理一个包含 DDBB 中 ID 的数组 ($original),然后,再用另一个数组来对应修改后要共享的用户 ID ($new)。哪些需要从 DDBB 中删除,哪些需要插入?

如果你进行简单的差异运算或其他操作,你会得到类似 C=1,4 的结果。
你不知道哪些需要插入,哪些需要删除。

但是用这种方法,你就能知道,这就是为什么:

- 留在 $original 中的内容,是修改前 $new 中没有的内容。所以,你知道了,$original 中的所有内容都需要从 DDBB 中删除,因为在修改过程中,你取消了对 $original 中的用户的选择。
- 留在 $new 中的内容,是修改前 $original 中没有的内容。这意味着在修改过程中,你添加了一些新用户。这些用户需要插入 DDBB 中。所以,$new 中的所有内容,都需要插入 DDBB 中。

结论

- 留在 $original 中 --> 从数据库中删除。
- 留在 $new 中 --> 插入数据库中。

就这样!

我希望你发现它有用,并且我鼓励 PHP "开发者" 在不久的将来,原生添加类似这样的功能,因为我敢肯定,我并不是第一个需要这种功能的人。

祝一切顺利,

光。
eugeny dot yakimovitch at gmail dot com
13 年前
注意,array_diff 不等同于

<?php
function fullArrayDiff($left, $right)
{
return
array_diff(array_merge($left, $right), array_intersect($left, $right));
}
?>

因为它是一个集合论的补集,就像

http://en.wikipedia.org/wiki/Complement_(set_theory)
Viking Coder
18 年前
对于任何想要双向 array_diff 的人 - 如 rudigier 在 noxx dot at 上所述。记住,array_diff 会返回第一个数组中所有不在后续数组中的元素。

$array1=array('blue','red','green');
$array2=array('blue','yellow','green');

array_merge(array_diff($array1, $array2),array_diff($array2, $array1));

结果
------
数组
(
[0] => red
[1] => yellow
)
yo at aaron dot com dot es
13 小时前
看起来当给定的数组之一是多维数组时,这会抛出警告

PHP Warning: Array to string conversion in Command line code on line 1

在这里分享,因为从错误或本页的文档中,我并不清楚这一点。

代码
<?php
php
-r 'array_diff(["a" => 1], ["b" => [ 1 ]]);'
?>

结果
PHP Warning: Array to string conversion in Command line code on line 1

Warning: Array to string conversion in Command line code on line 1
Sbastien
1 年前
我使用 array_diff() 和 array_intersect() 来检查 CSV 文件在处理前的完整性

<?php

$header
= fgetcsv($stream, ...$csv_options); // ['id', 'name', 'sex']

$awaited = ['id', 'name', 'email']; // CSV 中我需要的标题列

$present = array_intersect($header, $awaited); // ['id', 'name']

if (count($present) < count($awaited)) { // 2 < 3 => true, 问题!
$missing = array_diff($present, $awaited); // ['email']
$missing = join(', ', $missing);
echo
"缺少的列: {$missing}\r\n";
}
Anonymous
9 years ago
如果你没有得到 count(array_diff($a1,$a2))>0,而数组类似于以下内容,则应该使用 php.net/array_diff_assoc 函数。

$a1 = 数组
(
[0] => id
[1] => id_1
[2] => id_2
)

$a2 = 数组
(
[0] => id
[1] => id_2
[2] => id_1
)
ds2u at the hotmail dot com
21 年前
是的,你可以使用

<?php
$result
= array_values(array_diff($array1,$array2));
?>

来删除空白/缺失的键。但是,要删除从文件中读取时令人讨厌的索引的空格(实际上是一个换行符) - 只需使用差异

<?php
$array
= array ();
$array[0] = "\n";
$result = array_diff($result,$array);
?>

dst
j dot j dot d dot mol at ewi dot tudelft dot nl
19 年前
以下是一些用于获取两个数组差异的代码。它允许自定义修改,例如添加前缀字符串(如所示)或自定义比较函数。

<?php
// 在 O(n log n) 时间内返回 $all 中所有不在 $used 中的元素。
// $all 中的元素以 $prefix_all 为前缀。
// $used 中的元素以 $prefix_used 为前缀。
function filter_unused( $all, $used, $prefix_all = "", $prefix_used = "" ) {
$unused = array();

// 排序不需要前缀
sort( $all );
sort( $used );

$a = 0;
$u = 0;

$maxa = sizeof($all)-1;
$maxu = sizeof($used)-1;

while(
true ) {
if(
$a > $maxa ) {
// 完成;$used 的其余部分不在 $all 中
break;
}
if(
$u > $maxu ) {
// $all 的其余部分未被使用
for( ; $a <= $maxa; $a++ ) {
$unused[] = $all[$a];
}
break;
}

if(
$prefix_all.$all[$a] > $prefix_used.$used[$u] ) {
// $used[$u] 不在 $all 中?
$u++;
continue;
}

if(
$prefix_all.$all[$a] == $prefix_used.$used[$u] ) {
// $all[$a] 被使用
$a++;
$u++;
continue;
}

$unused[] = $all[$a];

$a++;
}

return
$unused;
}
?>
To Top