Как получить разницу двух многомерных массивов с разными ключами, но одинаковым значением в php?

#php #arrays

#php #массивы

Вопрос:

У меня есть два многомерных массива ниже.

1-й массив

 Array
(
    [ma] => Array
        (
            [mdesktopapps] => Array
                (
                    [0] => part1
                    [1] => part2
                )

        )

)
 

2-й массив

 Array
(
    [ma] => Array
        (
            [mdesktopapps] => Array
                (
                    [0] => part2
                )

        )

)
 

Я хочу получить разницу между приведенными выше массивами, и результат должен быть таким, как показано ниже

Желаемый результат

 Array
(
    [ma] => Array
        (
            [mdesktopapps] => Array
                (
                    [0] => part1
                )

        )

)
 

Я попытался получить вывод, используя приведенную ниже функцию, но не получил правильного вывода.

Функция, которую я использовал

 function array_diff_assoc_recursive($array1, $array2) {
    $difference=array();
    foreach($array1 as $key => $value) {
        if( is_array($value) ) {
            if( !isset($array2[$key]) || !is_array($array2[$key]) ) {
                $difference[$key] = $value;
            } else {
                $new_diff = array_diff_assoc_recursive($value, $array2[$key]);
                if( !empty($new_diff) )
                    $difference[$key] = $new_diff;
            }
        } else if( !array_key_exists($key,$array2) || $array2[$key] !== $value ) {
            $difference[] = $value;
        }
    }
    return $difference;
}
 

Вывод

 Array
(
    [ma] => Array
        (
            [mdesktopapps] => Array
                (
                    [0] => part1
                    [1] => part2
                )

        )

)
 

Комментарии:

1. Когда вы говорите «с разными ключами» , вы имеете в виду только нижний уровень, цифровые клавиши? Кроме того, есть ли еще ассоциативные ключи внутри вашего массива, где вы хотите выполнить эту операцию, или это mdesktopapps единственный?

2. да, нумировочные ключи нижнего уровня

Ответ №1:

Ваша проблема исходит из логики, которую вы вкладываете в условие else if:

 ...
} else if( !array_key_exists($key,$array2) || $array2[$key] !== $value ) {
...
 

Теперь, что вы здесь делаете, вы вызываете метод во второй раз, когда вы передаете свои массивы «ma», и вы начинаете повторять значения — «part1» и «part2», вы попадаете внутрь этого else, если и для первого значения «part1» вы выполняете это условие $array2 [$ key] !== $value, потому что в $array2 [$key] ($ array2[0]) значение равно «part2», а $value в этой первой итерации равно «part1», поэтому вы присваиваете это значение $difference[] . Пока все хорошо, но во время второй итерации, где значение равно «part2», вы фактически выполняете это условие — !array_key_exists($key,$array2), потому что ваш $array2 не имеет ключа 1, поэтому вы добавляете к $difference[] этот результат… Что вы можете сделать:

 // now i've added 3rd argument to the function called recursiveCount 
// by default is false so this count happens only if you pass true as 3rd arg
function array_diff_assoc_recursive($a, $b, $recursiveCount = false) {
        // by default we set $array1 to be $a and $array2 to be $b 
        $array1 = $a;
        $array2 = $b;
       // but if we "put the count flag" and if the first array we pass
       // is smaller that the 2nd we will reverse it
       // so you don't have to worry about if the 1st array you pass in the function is smaller than the 2nd
    if ($recursiveCount amp;amp; (count($array1, COUNT_RECURSIVE) < count($array2, COUNT_RECURSIVE))) {
        $array1 = $b;
        $array2 = $a;
    }

        $difference = [];
        foreach ($array1 as $key => $value) {
            if (is_array($value)) {
                if (!isset($array2[$key]) || !is_array($array2[$key])) {
                    $difference[$key] = $value;
                } else {

                    // now note that now when we call the function here we dont pass the 3rd argument, to count our arrays
                    $newDiff = $this->array_diff_assoc_recursive($value, $array2[$key]);
                    if (!empty($newDiff)) {
                        $difference[$key] = $newDiff;
                    }
                }
            } else {
                // also 1 small change here just in case arr2 is not an array actually
                if (is_array($array2) amp;amp; !in_array($value, $array2)) {
                    $difference[] = $value;
                } elseif (!is_array($array2) amp;amp; $value != $array2) {
                    $difference[] = $value;
                }
            }
        }

        return $difference;
    }
 

Теперь как использовать его с этим 3-м параметром:

     $aa = [
        "ma" => [
            "mdesktopapps" => ["part1","part2","part3","part4","part5"]
        ]
    ];

    $ab = [
        "ma" => [
            "mdesktopapps" => ["part2","part5","part4"]
        ]
    ];

    // note we pass true as 3rd arg, so we will count our multidimensional arrays
   // and because $ab < $aa they will be switched in out function
    $t = $this->array_diff_assoc_recursive($ab, $aa, true);

    var_dump($t);
 

Результат:

 array(1) {
  'ma' =>
  array(1) {
    'mdesktopapps' =>
    array(2) {
      [0] =>
      string(5) "part1"
      [1] =>
      string(5) "part3"
    }
  }
}
 

Вот и все, отсюда вы можете поиграть с ним и обновить его еще больше…

Комментарии:

1. Вау, Ангел, это сработало, большое спасибо. Позвольте мне проверить это с помощью нескольких разных массивов.

2. Я немного отредактировал функцию, чтобы вы не беспокоились, какой массив больше, и приведу пример использования

Ответ №2:

Для этой проблемы вы можете использовать функцию array_intersect, например:

 <?php
$arr1 = [
    "ma" => [
        "mdesktopapps" => [
            0 => "part1",
            1 => "part2"
        ],
    ],
];

$arr2 = [
    "ma" => [
        "mdesktopapps" => [
            0 => "part2"
        ],
    ],
];


$result = [
    "ma" => [
        "mdesktopapps" => array_intersect(
            $arr1['ma']['mdesktopapps'], 
            $arr2['ma']['mdesktopapps']
        )
    ],
];

print_r($result);
 

здесь можно протестировать этот PHP-код

Комментарии:

1. В моем случае это не сработает, так как ключи ‘ma’ или ‘mdesktopapp’ могут быть разными. Решение должно быть динамическим с использованием цикла или некоторых рекурсивных функций.