简体   繁体   中英

PHP compare two arrays and return only unique array values

Finishing up an open source Domain Registrar plugin and having a few troubles with determining when a change has been made.

$saved = array(
        array( 'domain' => 'mydomain.com', 'record' => 'A', 'value' => '8.8.8.8' ),
        array( 'domain' => 'mydomain.com', 'record' => 'NS', 'value' => 'ns1.mydomain.com' )
    );

$new = array(
        array( 'domain' => 'mydomain.com', 'record' => 'A', 'value' => '4.4.4.4' ),
        array( 'domain' => 'mydomain.com', 'record' => 'NS', 'value' => 'ns1.mydomain.com' ),
        array( 'domain' => 'sub.mydomain.com', 'record' => 'A', 'value' => '1.2.3.4' ),
    );

$saved is the values already saved at the domain registrar, and is only being used for comparison.

$new is the array returned from application that processed the form on the website.

I need to somehow only return arrays that have values that were updated or that do not already exist/match from $saved .

Basically the return array i'm looking for would be:

array(
    array( 'domain' => 'mydomain.com', 'record' => 'A', 'value' => '4.4.4.4' )
    array( 'domain' => 'sub.mydomain.com', 'record' => 'A', 'value' => '1.2.3.4' ),
);

Because in $saved the value was updated from 8.8.8.8 to 4.4.4.4 , and the sub.mydomain.com did not match any array from $saved meaning it's a new entry.

Using array_intersect I was able to get it to return the array that had it's values updated, but unfortunately it still includes the arrays that matched as well. If I could somehow have those removed that would be exactly what I need.

Here's a demo: http://glot.io/php/529b0c6d2fd16fe221f86bb521155384

Maybe use array_uintersect with a callback to check if the arrays match and unset? Looking for some help as i'm stuck on this now.

Thanks!!

Well in this case you could flatten them thru serializing, them map, them finally array_dif()

$result = array_map('unserialize', array_diff(array_map('serialize', $new), array_map('serialize', $saved)));

Should produce based on example:

Array
(
    [0] => Array
        (
            [domain] => mydomain.com
            [record] => A
            [value] => 4.4.4.4
        )

    [2] => Array
        (
            [domain] => sub.mydomain.com
            [record] => A
            [value] => 1.2.3.4
        )

)

array_udiff should work here.

Something along the lines of the following comparison function as a custom callback should do the trick:

$saved = array(
        array( 'domain' => 'mydomain.com', 'record' => 'A', 'value' => '8.8.8.8' ),
        array( 'domain' => 'mydomain.com', 'record' => 'NS', 'value' => 'ns1.mydomain.com' )
    );

$new = array(
        array( 'domain' => 'mydomain.com', 'record' => 'A', 'value' => '4.4.4.4' ),
        array( 'domain' => 'mydomain.com', 'record' => 'NS', 'value' => 'ns1.mydomain.com' ),
        array( 'domain' => 'sub.mydomain.com', 'record' => 'A', 'value' => '1.2.3.4' ),
    );


function cmpr($a, $b) {
    foreach($a as $k=>$v) {
        if ($b[$k] !== $v)
            return -1;
    }
    return 0;
}

var_dump(array_udiff($new, $saved, 'cmpr'));

The output should look something like what you expected:

array(2) {
  [0]=>
  array(3) {
    ["domain"]=>
    string(12) "mydomain.com"
    ["record"]=>
    string(1) "A"
    ["value"]=>
    string(7) "4.4.4.4"
  }
  [2]=>
  array(3) {
    ["domain"]=>
    string(16) "sub.mydomain.com"
    ["record"]=>
    string(1) "A"
    ["value"]=>
    string(7) "1.2.3.4"
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM