PHP Conference Japan 2024

array_diff

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

array_diff计算数组的差集

描述

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

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

参数

array

要从中比较的数组

arrays

要比较的数组

返回值

返回一个 数组,其中包含 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
// 这将生成一个通知,表明数组无法转换为字符串。
$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 循环通过键取消设置它,然后重新对数组进行键控。

<?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() 函数效率不高,且内存消耗较大。

根据我的经验,当我在大型数组(50k+ 键值对)上运行 array_diff() 时,几乎总是意识到我正在从错误的角度处理问题。

通常,在重新设计问题以避免使用 array_diff() 时,尤其是在处理大型数据集时,我会发现显著的性能提升和优化。
Al Amin Chayan (mail at chayan dot me)
4 年前
<?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
xmgr2 at protonmail dot com
2 个月前
描述乍一看有点模糊,人们可能会认为 array_diff 函数返回所有给定数组之间的差异(这正是我实际想要的,所以当示例代码的结果不包含“yellow”时我很惊讶)。

但是,我写了一个简洁的单行代码来计算所有给定数组之间的差异。

<?php
# 返回一个包含所有给定数组中唯一值的数组
function array_unique_values(...$arrays) {
return
array_keys(array_filter(array_count_values(array_merge(...$arrays)), fn($count) => $count === 1));
}

# 示例:
$array1 = ['a', 'b', 'c', 'd'];
$array2 = ['a', 'b', 'x', 'y'];
$array3 = ['a', '1', 'y', 'z'];

print_r(array_unique_values($array1, $array2, $array3));
?>

结果
数组
(
[0] => c
[1] => d
[2] => x
[3] => 1
[4] => z
)
Jeppe Utzon
12 年前
如果你只需要知道两个数组的值是否完全相同(无论键和顺序如何),那么可以使用这种简单的方法,而不是使用 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 );

?>

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

此外,如果两个数组包含不同数量的值,则哪种方法更快将取决于是否需要对两个数组进行排序。两次 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
23年前
我偶然发现了一个 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年前
如果第一个数组中出现重复的值,它也会被包含在内。请查看输出中“blue”出现了两次。

<?php

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

print_r($result);

//输出
//Array ( [1] => blue [3] => blue )
merlyn dot tgz at gmail dot com
12 年前
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年前
我一直希望有一些类似的东西来避免在项目目录中列出所有想要排除的文件和文件夹。

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));
Tim Trefren
16年前
这是一个用于 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;
}
?>
merlinyoda at dorproject dot net
16年前
正如 kitchin 在 2007 年 6 月 19 日 03:49 的评论和 nilsandre 在 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)
}
?>
Anonymous
21年前
来自页面
注意:请注意,此函数仅检查 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 年前
重新提交... 更新内容考虑了比较问题
计算所有数组的差异
<?php

/**
* array_diffs — 计算所有数组的差异
*
* @param array
*
* array1 - 要从中和针对其进行比较的数组
* array2 - 要从中和针对其进行比较的数组
* array(n) - 要从中和针对其进行比较的更多数组
*
* @return array 返回所有包含任何数组中无法匹配的条目的数组。
*/

function array_diffs() {
$count = func_num_args();
if(
$count < 2) {
trigger_error('必须至少提供两个数组进行比较。');
}
$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;
}

?>
Simon Riget 来自 paragi.dk
18 年前
一个简单的多维键感知 array_diff 函数。

<?php
function arr_diff($a1,$a2){
foreach(
$a1 as $k=>$v){
unset(
$dv);
if(
is_int($k)){
// 比较值
if(array_search($v,$a2)===false) $dv=$v;
else if(
is_array($v)) $dv=arr_diff($v,$a2[$k]);
if(
$dv) $diff[]=$dv;
}else{
// 比较非整数键
if(!$a2[$k]) $dv=$v;
else if(
is_array($v)) $dv=arr_diff($v,$a2[$k]);
if(
$dv) $diff[$k]=$dv;
}
}
return
$diff;
}
?>

此函数满足我的迫切需求,但我相信它可以改进。
vojtech dot hordejcuk at gmail dot com
15 年前
基于一位老兄的代码,我创建了以下函数来创建类似 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 年前
重新提交... 更新内容考虑了比较问题

计算所有数组的差异

<?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
10 年前
差异仅在第一层进行。如果您想比较两个数组,您可以使用以下网址提供的代码 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) ){
// 两个数组:继续深入...
// ... 并解释这是一个更新!
$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 年前
我需要一个函数,它只删除第二个数组中出现的元素的次数。换句话说,如果您有 Array(1, 1, 2) 和 Array(1),则返回值应为 Array(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){ //注意:如果您需要差异严格匹配,请删除两个“(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 )

请注意,它从左到右删除元素,与您可能预期的相反;在我的情况下,元素的顺序无关紧要。修复此问题需要进行一些小的修改。
匿名用户
15 年前
你好!
我努力寻找我将在此处解释的问题的解决方案,并且在阅读了所有数组函数和可能性之后,我不得不创建我认为应该存在于下一个 PHP 版本中的内容。

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

例如

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

不应该为

C = 1,4

而是

A = 1
B = 4

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

现在,我有一些操作需要执行,并且我知道要对来自哪个数组的值执行哪个操作。
使用普通的 DIFF 我无法做到,因为如果我有一个像 C=1,4 这样的数组,我不知道是应该对 1 执行 Action_A 还是对 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

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

想象一下,您有一些“事件”和一些您在创建事件时选择的用户可以“查看”您创建的此事件。所以你与一些用户“分享”这个事件。好的?

想象一下,您创建了一个 Event_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 “开发者”在不久的将来添加类似这样的原生功能,因为我相信我不是第一个需要这样的东西的人。

致以最诚挚的问候,

Light。
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 at 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
)
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";
}
匿名
9年前
如果您使用类似以下数组的内容没有获得 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