7

我有两个数组,这些数组包含有关id,的信息linklabelurl格式如下:

$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] 键,因此它忽略它们并返回$pageids从 [2] 开始的所有信息。但是,我希望它查看嵌套数组的内容并进行比较,例如,我需要它来查看哪些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',
  ),
)
4

5 回答 5

22

要检查多任务,请尝试以下操作:

$pageWithNoChildren = array_map('unserialize',
    array_diff(array_map('serialize', $pageids), array_map('serialize', $parentpage)));
  • array_map()运行主数组的每个子数组,通过serialize()它将每个子数组转换为该子数组的字符串表示
    • 主数组现在的值不是数组而是子数组的字符串表示
  • array_diff()现在每个数组都有一个一维数组来比较
  • 返回差异后,array_map()运行数组结果(差异)unserialize()以将字符串表示重新转换为子数组

量子点

于 2014-03-12T14:48:44.040 回答
4

来自@AbraCadaver 的非常好的解决方案,但就像我在评论中所说的那样,可能存在关联数组的元素在任何地方的顺序不同的情况,因此首先按索引/键对它们进行排序的自定义函数很方便:

function sortAndSerialize($arr){
    ksort($arr);
    return serialize($arr);
}

array_map('unserialize', array_diff(array_map('sortAndSerialize', $pageids), array_map('sortAndSerialize', $parentpage)));
于 2016-08-07T12:42:46.587 回答
2

正确的方式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;
    }
}
于 2018-07-30T12:02:15.380 回答
1

来自@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))
);
于 2020-01-09T08:00:35.207 回答
0

最简单的是,调用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 的答案相同的结果,但我的片段做的工作要少得多。

于 2022-02-20T13:49:14.200 回答