我有一个包含关联数据行的数组。
$array1 = array(
array('ITEM' => 1),
array('ITEM' => 2),
array('ITEM' => 3),
);
我有第二个数组,也包含关联数据行,我想使用第一个数组进行过滤。
$array2 = array(
array('ITEM' => 2),
array('ITEM' => 3),
array('ITEM' => 1),
array('ITEM' => 4),
);
这感觉像是
array_diff()
的工作,但是我如何才能专门比较更深的 ITEM
值上的行?
如何过滤第二个数组并得到以下结果?
array(3 => array('ITEM' => 4))
array_udiff()
定义自定义比较函数。
function udiffCompare($a, $b)
{
return $a['ITEM'] - $b['ITEM'];
}
$arrdiff = array_udiff($arr2, $arr1, 'udiffCompare');
print_r($arrdiff);
输出:
Array
(
[3] => Array
(
[ITEM] => 4
)
)
这使用并保留了数组的现有结构,我认为这是您想要的。
我可能会迭代原始数组并使它们成为一维......类似
foreach($array1 as $aV){
$aTmp1[] = $aV['ITEM'];
}
foreach($array2 as $aV){
$aTmp2[] = $aV['ITEM'];
}
$new_array = array_diff($aTmp1,$aTmp2);
另一种有趣的方法,带有
json_encode
技巧(如果您需要“原始”比较第一级数组中的一些复杂值,则非常有用):
// Compare all values by a json_encode
$diff = array_diff(array_map('json_encode', $array1), array_map('json_encode', $array2));
// Json decode the result
$diff = array_map('json_decode', $diff);
array_filter
的几个解决方案的性能低于array_udiff
解决方案的大型数组,但更简单、更灵活:
$array1 = [
['ITEM' => 1],
['ITEM' => 2],
['ITEM' => 3],
];
$array2 = [
['ITEM' => 2],
['ITEM' => 3],
['ITEM' => 1],
['ITEM' => 4],
];
$arrayDiff = array_filter($array2, function ($element) use ($array1) {
return !in_array($element, $array1);
});
// OR
$arrayDiff = array_filter($array2, function ($array2Element) use ($array1) {
foreach ($array1 as $array1Element) {
if ($array1Element['ITEM'] == $array2Element['ITEM']) {
return false;
}
}
return true;
});
与
array_filter
一样,请注意 array_filter
保留原始数组的键,因此如果您希望 $arrayDiff
为零索引,请在 $arrayDiff = array_values($arrayDiff);
调用之后执行 array_filter
。
您可以使用下面的代码来获得差异。
array_diff(array_column($a1, 'ITEM'), array_column($a2, 'ITEM'));
array_udiff()
,以超越所有其他可以做到这一点的技术。
对于您的场景,您正在寻求一种过滤
array_diff()
来评估第一级“值”(数据行)内的数据。 在自定义函数中,必须隔离特定列以进行比较。 有关所有本机 array_diff()
函数变体的列表,请参阅 此答案。
要使用第一个数组过滤第二个数组(并输出第二个数组中保留的数据),必须将
$array2
写为第一个参数,将 $array1
写为第二个参数。
利用的 array_diff()
和 array_intersect()
函数(函数名称中包含 u
)期望整数作为其返回值。 该值用于在实际执行评估之前对数据进行初步排序——这是一种性能优化。 可能存在这样的情况:如果您只返回 0
或 1
(不是三向比较),那么结果可能会出乎意料。 为了确保结果稳定,请始终提供可以返回负整数、正整数和零整数的比较函数。
比较整数值时,减法 (
$a - $b
) 将给出可靠的返回值。 为了在比较浮点值或非数字数据时获得更大的实用性,当您的 PHP 版本可用时,您可以使用 spaceship 运算符。
代码:(演示)
var_export(
array_udiff($array2, $array1, fn($a, $b) => $a['ITEM'] <=> $b['ITEM'])
);
var_export(
array_udiff(
$array2,
$array1,
function($a, $b) {
return $a['ITEM'] <=> $b['ITEM'];
}
)
);
var_export(
array_udiff(
$array2,
$array1,
function($a, $b) {
return $a['ITEM'] === $b['ITEM']
? 0
: ($a['ITEM'] > $b['ITEM'] ? 1 : -1);
}
)
);
以上所有版本的输出:
array (
3 =>
array (
'ITEM' => 4,
),
)
使用对象数组时,技术是相同的;只是访问属性的语法与访问数组元素不同(
$a['ITEM']
是 $a->ITEM
)。
对于与一个数组隔离的元素在另一个数组中不存在的情况,您需要将
$a
和 $b
数据合并到相反的后备列,因为来自第一个数组和第二个数组的数据将在回调的两个参数中都表示。
代码:(演示)
$array1 = array(
array('ITEM' => 1),
array('ITEM' => 2),
array('ITEM' => 3),
);
$array2 = array(
array('ITEMID' => 2),
array('ITEMID' => 3),
array('ITEMID' => 1),
array('ITEMID' => 4),
);
// PHP7.4+ (arrow functions)
var_export(
array_udiff(
$array2,
$array1,
fn($a, $b) => ($a['ITEM'] ?? $a['ITEMID']) <=> ($b['ITEM'] ?? $b['ITEMID'])
)
);
或者因为仅比较两个数据集中的第一列值:
var_export(
array_udiff($array2, $array1, fn($a, $b) => current($a) <=> current($b))
);
最后,由于两个输入数组的行都包含相同的结构,因此您可以简单地比较整行。 演示
var_export(
array_udiff(
$array2,
$array1,
fn($a, $b) => $a <=> $b
)
);
有同样的问题,但我的多维数组有各种键,与每个数组中一致的“ITEM”不同。
解决了:
$result = array_diff_assoc($array2, $array1);
另一种解决方案 if( json_encode($array1) == json_encode($array2) ){ ... }
将 array1 与一个或多个其他数组进行比较,并返回 array1 中不存在于任何其他数组中的值。
//Enter your code here, enjoy!
$array1 = array("a" => "green", "red", "blue");
$array2 = array("b" => "green", "yellow", "red");
$result = array_diff($array1, $array2);
print_r($result);