Difference between two Multidimensional Arrays with PHP

Asked

Viewed 873 times

3

I have these two multidimensional arrays and would like the difference between them, similar to what the function array_diff does, but with multidimensional arrays:

$array_1:

Array
(
    [0] => Array
        (
            [idAmbiente] => 1
            [nomeAmbiente] => Desenvolvimento
            [codAmbiente] => D
        )

    [1] => Array
        (
            [idAmbiente] => 2
            [nomeAmbiente] => Produção
            [codAmbiente] => P
        )

    [2] => Array
        (
            [idAmbiente] => 3
            [nomeAmbiente] => Testes
            [codAmbiente] => T
        ) 
)

$array_2:

Array
(
    [0] => Array
        (
            [idVisibilidade] => 14
            [urlSistema] => http://www-gexdia/prevsuporte
            [responsavelVisibilidade] => 12
            [sistema_idSistema] => 10
            [idAmbiente] => 2
            [dataBaseList] => 18
        ) 
)

I’d like the function to do something like: array_diff_multidimensional($array_1,$array_2,'idAmbiente');

Upshot:

Array
( 
    [0] => Array
        (
            [idAmbiente] => 1
            [nomeAmbiente] => Desenvolvimento
            [codAmbiente] => D
        )

    [1] => Array
        (
            [idAmbiente] => 3
            [nomeAmbiente] => Testes
            [codAmbiente] => T
        ) 
)

2 answers

4


I’ve done two jobs, array_enkeyize to transform the value of an item into a key in the arrays and array_dekeyize to traffic the key in a value of a declared item in the parameters

function array_enkeyize($array, $iten) {
  foreach ($array as $key => $value) {
    foreach ($value as $v_key => $v_value) {
        if ($v_key === $iten){
            $keized[$v_value] = $array[$key];
            unset($keized[$v_value][$iten]);
        }     
    }
  }

  return $keized;
}


function array_dekeyize($array, $iten) {
    $i = 0;
  foreach ($array as $key => $value) {      
    $dekeized[$i] = $array[$key];
    $dekeized[$i++][$iten] = $key; 
  }

  return $dekeized;
}

How to use

$array1 = array_enkeyize($array_1, 'idAmbiente');
$array2 = array_enkeyize($array_2, 'idAmbiente');

$result = array_diff_key($array1, $array2);

$result = array_dekeyize($result, 'idAmbiente');

var_dump($result);

Upshot

array (size=2)
  0 => 
    array (size=3)
      'nomeAmbiente' => string 'Desenvolvimento' (length=15)
      'codAmbiente' => string 'D' (length=1)
      'idAmbiente' => int 1
  1 => 
    array (size=3)
      'nomeAmbiente' => string 'Testes' (length=6)
      'codAmbiente' => string 'T' (length=1)
      'idAmbiente' => int 3

=)

2

Since the key is relevant to the comparison between the arrays (idAmbiente), what you are looking for is something closer to a array_diff_assoc

Because its arrays are multidimensional, it will take a recursive function to traverse and compare the internal arrays. In the comments of the php documentation itself we have the implementation of recursive function that you need:

<?php
function array_diff_assoc_recursive($array1, $array2)
{
    foreach($array1 as $key => $value)
    {
        if(is_array($value))
        {
              if(!isset($array2[$key]))
              {
                  $difference[$key] = $value;
              }
              elseif(!is_array($array2[$key]))
              {
                  $difference[$key] = $value;
              }
              else
              {
                  $new_diff = array_diff_assoc_recursive($value, $array2[$key]);
                  if($new_diff != FALSE)
                  {
                        $difference[$key] = $new_diff;
                  }
              }
          }
          elseif(!isset($array2[$key]) || $array2[$key] != $value)
          {
              $difference[$key] = $value;
          }
    }
    return !isset($difference) ? 0 : $difference;
} 

How this function uses isset, if your array has a key with null, the result may not be as expected, as the isset will return to position in null even if they marry between arrays:

<?php

$array1 = array('a' => null, 'b' => null);
$array2 = array('a' => null);

var_dump(array_diff_assoc_recursive($array1, $array2));

Returns:

array(1) {
  [0]=>
  array(2) {
    ["a"]=>
    NULL
    ["b"]=>
    NULL
  }
}

To circumvent this situation, in the comments of the same function, we have a implementation that replaces the isset for array_key_exists.

I recommend using the implementation with array_key_exists only if you accurate the truth of the difference between null keys. Recursive functions are slower by nature, and how the isset is faster than array_key_exists for being a language constructor and not a function, in cases of giant arrays the isset will perform better.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.