2

I have two arrays.

$arr1 = array(
    'name',
    'date' => array('default' => '2009-06-13', 'format' => 'short'),
    'address',
    'zipcode' => array('default' => 12345, 'hidden' => true)
);

$arr2 = array(
    'name',
    'language',
    'date' => array('format' => 'long', 'hidden' => true),
    'zipcode' => array('hidden' => false)
);

Here's the desired result:

$final = array(
    'name',
    'date' => array('default' => '2009-06-13', 'format' => 'long', 'hidden' => true),
    'zipcode' => array('default' => 12345, 'hidden' => false)
);
  • Only the elements from $arr2 (that also exist in $arr1) are used
  • Each element's attributes are merged
  • If a common element (e.g. zipcode) shares an attribute (e.g. hidden), then the attribute from $arr2 takes precedence

What are some good approaches for solving this problem?

I tried to hobble something together... critiques welcomed:**

$new_array = array_intersect_key($arr2, $arr1);

foreach ($new_array as $key => $val)
{
    if (is_array($arr1[$key]))
    {
        if (is_array($val))
        {
            $new_array[$key] = array_merge($val, $arr1[$key]);
        }
        else
        {
            $new_array[$key] = $arr1[$key];
        }
    }
}
5
  • 1
    Good practice in this case is to post code like that as an answer to your own question. Commented Jun 14, 2009 at 3:01
  • The problem is that the above "solution" doesn't work... Commented Jun 14, 2009 at 3:06
  • I was looking at this but am wondering about a slight inconsistency. You only care about matching for the first-dimension of the array, and then merge everything in the second dimension, overwriting? Also, will this ever extend past two dimensions? Commented Jun 14, 2009 at 3:12
  • This will never extend past two dimensions. And yes, the $arr1's element's attributes will get overwritten by any matching $arr2 attributes. Commented Jun 14, 2009 at 3:22
  • My updated solution should be fixed now Commented Jun 14, 2009 at 4:06

2 Answers 2

2

You were close

$newArr = array_intersect_key($arr1, $arr2);
foreach ($newArr as $key => $val)
{
    if (is_array($val))
    {
        $newArr[$key] = array_merge($arr1[$key], $arr2[$key]);
    }
}

Edit Just had to change the array_intersect to array_intersect_key

Sign up to request clarification or add additional context in comments.

2 Comments

That doesn't look quite right either. If $arr1['address'] is an array, then it still makes it to the final output... :\
I didn't really check it throughly, it just gave me the proper result so I stopped :x. Let me have another look.
0

Your described logic appears to:

  • retain the indexed values of the first array which are found as indexed values of the second array, and
  • overwrite the subarray elements of associative values in the first array which with corresponding subarrays of the second array.

It is unclear/unknown if an associative element might not have a subarray, so this is not built into the sceipt below. Demo

$arr2List = array_filter(
    $arr2,
    is_int(...),
    ARRAY_FILTER_USE_KEY
);

$result = [];
foreach ($arr1 as $k => $v) {
    if (is_int($k)) {
        if (in_array($v, $arr2List)) {
            $result[] = $v;
        }
    } elseif (
        is_array($v)
        && is_array($arr2[$k] ?? null)
    ) {
        $result[$k] = array_replace($v, $arr2[$k]);
    }
}
var_export($result);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.