Showing posts with label PHP array_replace_recursive. Show all posts
Showing posts with label PHP array_replace_recursive. Show all posts

Thursday, 30 August 2018

PHP merges two arrays on the same key value AND


I have two arrays. And I want to merge them on the same key AND value. If they have the same ur_user_id then they are merged. array2 only provides some additional data for array1, so the new_array.length = array1.length. array1 just gets the additional data from array2.


$array1 =
    array(
        array('ur_user_id'=> 1,'ur_fname'=>'PerA','ur_lname'=>'SonA'),
        array('ur_user_id'=> 2,'ur_fname'=>'PerB','ur_lname'=>'SonB'),
        array('ur_user_id'=> 3,'ur_fname'=>'PerC','ur_lname'=>'SonC'),
    );
$array2 =
    array(
        array('ur_user_id' => 5,'ur_code' => 'EE','ur_user_role' => 'testE'),
        array('ur_user_id' => 4,'ur_code' => 'DD','ur_user_role' => 'testD'),
        array('ur_user_id' => 6,'ur_code' => 'FF','ur_user_role' => 'testF'),
        array('ur_user_id' => 3,'ur_code' => 'CC','ur_user_role' => 'testC'),
        array('ur_user_id' => 1,'ur_code' => 'AA','ur_user_role' => 'testA'),
        array('ur_user_id' => 2,'ur_code' => 'BB','ur_user_role' => 'testB'),
    );

Then the new array must look like this. It will have both the values from the array1and array2.
$new_array =
    array(
        array('ur_user_id'=> 1,'ur_fname'=>'PerA','ur_lname'=>'SonA','ur_code' => 'AA','ur_user_role' => 'testA'),
        array('ur_user_id'=> 2,'ur_fname'=>'PerB','ur_lname'=>'SonB','ur_code' => 'BB','ur_user_role' => 'testB'),
        array('ur_user_id'=> 3,'ur_fname'=>'PerC','ur_lname'=>'SonC','ur_code' => 'CC','ur_user_role' => 'testC'),
    );

The array1.length is always less than or equal to array2.length never greater. And the order of both arrays will not be always ordered. I've tried the function below which I got somewhere here but it doesn't work for me and I'm not really good with loops.
function merge_common_keys(){
    $arr = func_get_args();
    $num = func_num_args();

    $keys = array();
    $i = 0;
    for ($i=0; $i<$num; ++$i){
        $keys = array_merge($keys, array_keys($arr[$i]));
    }
    $keys = array_unique($keys);

    $merged = array();

    foreach ($keys as $key){
        $merged[$key] = array();
        for($i=0; $i<$num; ++$i){
            $merged[$key][] = isset($arr[$i][$key]) ? $arr[$i][$key] : null;
        }
    }
    return $merged;
}

Based on the given arrays the result is like this. It only merges on the same key.
Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [ur_user_id] => 1
                    [ur_fname] => PerA
                    [ur_lname] => SonA
                )

            [1] => Array
                (
                    [ur_user_id] => 5
                    [ur_code] => AA-BB-CC
                    [ur_user_role] => testE
                )

        )


Try out this code, It might help you, it's short and without traversing loops:
    usort($array2,function($a,$b){
        return strnatcmp($a['ur_user_id'],$b['ur_user_id']);
    });
    $array3 = array_replace_recursive($array1, $array2);

    $result = array_uintersect($array3,$array1,function($a,$b){
        return strnatcmp($a['ur_user_id'],$b['ur_user_id']);
    });
    print_r($result);

Output
Array
(
    [0] => Array
        (
            [ur_user_id] => 1
            [ur_fname] => PerA
            [ur_lname] => SonA
            [ur_code] => AA
            [ur_user_role] => testA
        )

    [1] => Array
        (
            [ur_user_id] => 2
            [ur_fname] => PerB
            [ur_lname] => SonB
            [ur_code] => BB
            [ur_user_role] => testB
        )

    [2] => Array
        (
            [ur_user_id] => 3
            [ur_fname] => PerC
            [ur_lname] => SonC
            [ur_code] => CC
            [ur_user_role] => testC
        )

)


Friday, 27 March 2015

PHP: array_merge_recursive() vs. array_replace_recursive()

If you’ve been coding in PHP for a while, you have probably used array_merge() at some point. It’s been around since PHP 4, and like most PHP functions, it does largely what you’d expect it to do. If you have arrays with numeric indices, it re-indexes and appends subsequent arrays to the first array argument.
print_r(array_merge(
    array('a', 'b'),
    array('c', 'd')
));
/* the above will output:
Array
(
    [0] => a
    [1] => b
    [2] => c
    [3] => d
)
*/
If you have associative arrays, it doesn’t make much sense to re-index them. Instead, non-numeric keys are … well, merged. Keys from subsequent arrays will overwrite keys with the same name in earlier arrays.
/* note that the key 'B' appears in both arrays */
print_r(array_merge(
    array('A' => 1, 'B' => 2),
    array('B' => 20, 'C' => 30)
));
/* the above will output:
Array
(
    [A] => 1
    [B] => 20
    [C] => 30
)
*/
This is all pretty intuitive. But it gets trickier when you have nested associative arrays to merge. For example, you may have decoded the results from two JSON service calls into arrays, and they both have a top-level data key. array_merge() is not as useful in this case:
print_r(array_merge(
    array(
        'data' => array(
            'collision' => 'first',
            'unique1' => 1,
        )
    ),
    array(
        'data' => array(
            'collision' => 'second',
            'unique2' => 2,
        )
    )
));
/* the above will output:
Array
(
    [data] => Array
        (
            [collision] => second
            [unique2] => 2
        )
)
*/
The first array got clobbered — not quite what you expected, right? Fortunately, there’s a function that will do what you probably want: array_merge_recursive().
print_r(array_merge_recursive(
    array(
        'data' => array(
            'collision' => 'first',
            'unique1' => 1,
        )
    ),
    array(
        'data' => array(
            'collision' => 'second',
            'unique2' => 2,
        )
    )
));
/* the above will output:
Array
(
    [data] => Array
        (
            [collision] => Array
                (
                    [0] => first
                    [1] => second
                )
            [unique1] => 1
            [unique2] => 2
        )
)
*/
In some cases, this behavior isn’t actually what you want. One example is parsing hierarchical config files. If you had a default config and you wanted to merge in a user-specific config, you probably don’t want keys to be merged the way array_merge_recursive() does it. Instead, you would want the user-specific config to replace the default config’s value for that particular key. If you’re running PHP before version 5.3, you’d have to write a custom function to do this. But as of PHP 5.3, there is a new function that does exactly what you want: array_replace_recursive().
print_r(array_replace_recursive(
    array(
        'data' => array(
            'collision' => 'first',
            'unique1' => 1,
        )
    ),
    array(
        'data' => array(
            'collision' => 'second',
            'unique2' => 2,
        )
    )
));
/* the above will output:
Array
(
    [data] => Array
        (
            [collision] => second
            [unique1] => 1
            [unique2] => 2
        )
)
*/
If you’ve written a custom version of array_replace_recursive() and would like to switch to the built-in version, one helpful commenter suggests replacing your custom version with a wrapper that just calls array_replace_recursive(). There are also a few pure-PHP implementations of array_replace_recursive() if you’re stuck with an older version of PHP.