我有两个数组,这些数组包含有关id
、linklabel
和url
的信息,格式如下:
$pageids = [
['id' => 1, 'linklabel' => 'Home', 'url' => 'home'],
['id' => 2, 'linklabel' => 'Graphic Design', 'url' => 'graphicdesign'],
['id' => 3, 'linklabel' => 'Other Design', 'url' => 'otherdesign'],
['id' => 6, 'linklabel' => 'Logo Design', 'url' => 'logodesign'],
['id' => 15, 'linklabel' => 'Content Writing', 'url' => 'contentwriting'],
];
$parentpage = [
['id' => 2, 'linklabel' => 'Graphic Design', 'url' => 'graphicdesign'],
['id' => 3, 'linklabel' => 'Other Design', 'url' => 'otherdesign'],
];
我现在正在尝试比较这两者,以便找到$pageids
中但不在$parentpage
中的信息 - 这将构成另一个称为 $pageWithNoChildren
的数组。但是,当我使用以下代码时:
$pageWithNoChildren = array_diff_assoc($pageids,$parentpage);
array_diff_assoc()
在数组的第一级上运行,因此看到$pageids
和$parentpages
都有一个 [0] 和 [1] 键,因此它忽略它们并返回从 [2] 开始$pageids
的所有信息。但是,我希望它查看嵌套数组的内容并比较这些内容,例如我需要它来查看哪些id
、linklabel
和url
$pageids
而不是$parentpages
并返回这些值。
如何让array_diff_assoc()
在嵌套数组的键上运行,而不是在第一个数组的键上运行,因此最终结果是一个包含 [0]、[3] 和 [4] 数组内容的数组 $pageids
?
预期成果:
array (
0 =>
array (
'id' => 1,
'linklabel' => 'Home',
'url' => 'home',
),
3 =>
array (
'id' => 6,
'linklabel' => 'Logo Design',
'url' => 'logodesign',
),
4 =>
array (
'id' => 15,
'linklabel' => 'Content Writing',
'url' => 'contentwriting',
),
)
要检查多点,请尝试以下操作:
$pageWithNoChildren = array_map('unserialize',
array_diff(array_map('serialize', $pageids), array_map('serialize', $parentpage)));
-
array_map()
通过serialize()
运行主数组的每个子数组,将每个子数组转换为该子数组的字符串表示形式- 主数组现在的值不是数组,而是子数组的字符串表示形式
-
array_diff()
现在为每个数组都有一个一维数组
进行比较 - 返回差值后
array_map()
通过unserialize()
运行数组结果(差值(以将字符串表示形式转换回子数组
质检部
@AbraCadaver非常好的解决方案,但就像我在评论中所说的那样,在某些情况下,关联数组的元素在任何地方的顺序都不相同,因此首先按索引/键对它们进行排序的自定义函数很方便:
function sortAndSerialize($arr){
ksort($arr);
return serialize($arr);
}
array_map('unserialize', array_diff(array_map('sortAndSerialize', $pageids), array_map('sortAndSerialize', $parentpage)));
正确的方式 https://github.com/yapro/helpers/blob/master/src/ArrayHelper.php
class ArrayHelper
{
/**
* @param array $array1
* @param array $array2
* @return array
*/
function arrayDiffAssocMultidimensional(array $array1, array $array2): array
{
$difference = [];
foreach ($array1 as $key => $value) {
if (is_array($value)) {
if (!array_key_exists($key, $array2)) {
$difference[$key] = $value;
} elseif (!is_array($array2[$key])) {
$difference[$key] = $value;
} else {
$multidimensionalDiff = $this->arrayDiffAssocMultidimensional($value, $array2[$key]);
if (count($multidimensionalDiff) > 0) {
$difference[$key] = $multidimensionalDiff;
}
}
} else {
if (!array_key_exists($key, $array2) || $array2[$key] !== $value) {
$difference[$key] = $value;
}
}
}
return $difference;
}
}
@AbraCadaver的出色回答和@qdev非常观察的评论。我的建议只是一个很小的调整,以使已经提出的答案@qdev更便携。将函数分配给变量使其也可以在类方法等中使用。
$sortAndSerialize = function ($arr)
{
ksort($arr);
return serialize($arr);
};
$pageWithNoChildren = array_map(
'unserialize',
array_diff(array_map($sortAndSerialize, $pageids),
array_map($sortAndSerialize, $parentpage))
);
最简单的是,调用 array_udiff()
以利用对行进行 3 向比较(无迭代函数调用,无序列化(的回调。
如果行具有不同顺序的关联键,这仍然有效 - 无需排序。
代码:(演示(
$pageids = [
['id' => 1, 'linklabel' => 'Home', 'url' => 'home'],
['id' => 2, 'linklabel' => 'Graphic Design', 'url' => 'graphicdesign'],
['id' => 3, 'linklabel' => 'Other Design', 'url' => 'otherdesign'],
['id' => 6, 'linklabel' => 'Logo Design', 'url' => 'logodesign'],
['id' => 15, 'linklabel' => 'Content Writing', 'url' => 'contentwriting'],
];
$parentpage = [
['id' => 2, 'linklabel' => 'Graphic Design', 'url' => 'graphicdesign'],
['url' => 'otherdesign', 'id' => 3, 'linklabel' => 'Other Design'],
];
var_export(
array_udiff($pageids, $parentpage, fn($a, $b) => $a <=> $b)
);
输出:
array (
0 =>
array (
'id' => 1,
'linklabel' => 'Home',
'url' => 'home',
),
3 =>
array (
'id' => 6,
'linklabel' => 'Logo Design',
'url' => 'logodesign',
),
4 =>
array (
'id' => 15,
'linklabel' => 'Content Writing',
'url' => 'contentwriting',
),
)
假设提问者的示例数据不指示打乱的子数组键,我的示例输入将破坏@AbraCadaver和@Lebnik的算法,并导致它们给出与预期不同的结果。 我的片段给出的结果与@qdev和@Gruber的答案相同,但我的片段所做的工作要少得多。