1

Possible Duplicate:
recursive array_diff()?

I have a static multidimensional array which is always going to be in the same form. E.g. it will have the same keys & hierarchy.

I want to check a posted array to be in the same 'form' as this static array and if not error.

I have been trying various methods but they all seem to end up with a lot of if...else components and are rather messy.

Is there a succinct way to achieve this?


In response to an answer from dfsq:

$etalon = array(
    'name' => array(),
    'income' => array(
        'day'   => '',
        'month' => array(),
        'year'  => array()
    ),
    'message' => array(),
);

$test = array(
    'name' => array(),
    'income' => array(
        'day'   => '',
        'month' => array(),
        'year'  => array()
    ),
    'message' => array(),
);

// Tests
$diff = array_diff_key_recursive($etalon, $test);
var_dump(empty($diff));
print_r($diff);

And the results from that are

bool(false) 
Array ( [name] => 1 [income] => Array ( [month] => 1 [year] => 1 ) [message] => 1 ) 
Community
  • 1
  • 1
Julian S
  • 93
  • 1
  • 7

4 Answers4

5

Author needs a solution which would test if the structure of the arrays are the same. Next function will make a job.

/**
 * $a1 array your static array.
 * $a2 array array you want to test.
 * @return array difference between arrays. empty result means $a1 and $a2 has the same structure.
 */ 
function array_diff_key_recursive($a1, $a2)
{
    $r = array();

    foreach ($a1 as $k => $v)
    {
        if (is_array($v))
        {
            if (!isset($a2[$k]) || !is_array($a2[$k]))
            {
                $r[$k] = $a1[$k];
            }
            else
            {
                if ($diff = array_diff_key_recursive($a1[$k], $a2[$k]))
                {
                    $r[$k] = $diff;
                }
            }
        }
        else
        {
            if (!isset($a2[$k]) || is_array($a2[$k]))
            {
                $r[$k] = $v;
            }
        }
    }

    return $r;
}

And test it:

$etalon = array(
    'name' => '',
    'income' => array(
        'day'   => '',
        'month' => array(),
        'year'  => array()
    ),
    'message' => ''
);

$test = array(
    'name' => 'Tomas Brook',
    'income' => array(
        'day'   => 123,
        'month' => 123,
        'year'  => array()
    )
);

// Tests
$diff = array_diff_key_recursive($etalon, $test);
var_dump(empty($diff));
print_r($diff);

This will output:

bool(false)
Array
(
    [income] => Array
    (
        [month] => Array()

    )

    [message] => 
)

So checking for emptiness of $diff array will tell you if arrays have the same structure.

Note: if you need you can also test it in other direction to see if test array has some extra keys which are not present in original static array.

dfsq
  • 191,768
  • 25
  • 236
  • 258
  • Thanks I am giving this a go currently! – Julian S Oct 12 '11 at 13:55
  • Hi there, this doesnt seem to work properly im afraid. When the you put the `$a1` & `$a2` as the same structure it still gives an output of `Array ( [income] => Array ( [month] => 1 [year] => 1 ) ) ` Which suggests it has a problem with the empty arrays of `'month'` & `'year'` in the `$a1` array. – Julian S Oct 12 '11 at 14:13
  • Well if you define $a1 = Array([income] => Array( [month] => Array() [year] => Array() ) ), then its structure differs from $a2 = Array([income] => Array( [month] => 1 [year] => 1 ) ), because 1 is a scalar, not an array. If I understand what you mean. – dfsq Oct 12 '11 at 14:29
  • Sorry, the `Array ( [income] => Array ( [month] => 1 [year] => 1 ) )` was the return from the function e.g. it thought they were different. – Julian S Oct 12 '11 at 14:37
  • Could you post the example of your arrays so that I could see? Because for my arrays function works fine.. – dfsq Oct 12 '11 at 14:42
  • put code in my original question – Julian S Oct 12 '11 at 14:50
  • Well see: you have $etalon['name'] = array(), while $test['name'] = ''. So the comparison result is reasonable, arrays have different structure. – dfsq Oct 12 '11 at 14:57
  • Hi sorry that was a mistake in copying have amended as per my question. – Julian S Oct 12 '11 at 15:01
  • Oh, damn! sorry!! it was a mistake in my function that i forgot to fix. I fixed it in my testing script but not here. Check updated array_diff_key_recursive function (last line return $r; changes)! – dfsq Oct 12 '11 at 15:17
3

You could user array_intersect_key() to check if they both contain the same keys. If so, the resulting array from that function will contain the same values as array_keys() on the source array.

AFAIK those functions aren't recursive, so you'd have to write a recursion wrapper around them.

See User-Notes on http://php.net/array_diff_key

hakre
  • 193,403
  • 52
  • 435
  • 836
CodeCaster
  • 147,647
  • 23
  • 218
  • 272
1

Are you searching for the array_diff or array_diff_assoc functions?

Gianpaolo Di Nino
  • 1,139
  • 5
  • 17
0

use foreach with the ifs...if u have different tests for the different inner keys eg

$many_entries = ("entry1" = array("name"=>"obi", "height"=>10));   

and so on, first define functions to check the different keys then a foreach statement like this

foreach($many_entries as $entry)
    { 
        foreach($entry as $key => $val) 
            {
                switch($key)
                    {
                        case "name": //name function
                            //and so on
                    }
            }
    }
Obi Ik
  • 159
  • 2
  • 9