Search code examples
phparraysarray-merge

Merge 2 arrays in PHP, keeping only keys from first array


I have these two arrays:

$list = [
    'fruit' => [],
    'animals' => [],
    'objects' => [],
];

$dataArray = [
    'fruit' => 'apple',
    'animals' => ['dog', 'cat'],
    'asd' => 'bla'
];

I want to merge them so that $list at the end is:

[fruit] => Array
    (
        [0] => apple
    )

[animals] => Array
    (
        [0] => dog
        [1] => cat
    )

[objects] => Array
    (
    )

so, things to pay attention to:

  1. even if 'fruit' had only one element, is still an array in $list
  2. keys missing from $list ('asd' key) are simply ignored
  3. keys with no values are still kept, even if empty

Using array_merge doesn't work:

$merged = array_merge($list, $dataArray);

[fruit] => apple
[animals] => Array
    (
        [0] => dog
        [1] => cat
    )

[objects] => Array
    (
    )

[asd] => bla

I managed to get what I want with this:

foreach ($dataArray as $key => $value) {
    if (isset($list[$key])) {
        if (is_array($value)) {
            $list[$key] = $value;
        }
        else {
            $list[$key] = [$value];
        }

    }

}

But I was wondering if there was a cleaner way to do it or some other php function that I'm not aware of.


Solution

  • The second rule ("2. keys missing from $list ('asd' key) are simply ignored") tells me to iterate over $list, not over $dataArray. If $dataArray is much bigger than $list, iterating over it is a waste of time as most of its elements are simply ignored.

    Your rules do not explain how to process the elements of $list when they are not empty (I'll assume they are always arrays, otherwise the game changes and it becomes too complicated to provide generic code to handle it).

    The code I suggest looks like this:

    // Build the result in $result
    // (you can modify $list as well if you prefer it that way)
    $result = array();
    
    // 2. keys missing from $list ('asd' key) are simply ignored
    // iterate over the keys of $list, handle only the keys present in $dataArray
    foreach ($list as $key => $value) {
        if (array_key_exists($dataArray, $key)) {
            // $key is present in $dataArray, use the value from $dataArray
            $value = $dataArray[$key];
    
            // 1. even if 'fruit' had only one element, is still an array in $list
            if (! is_array($value)) {
                $value = array($value);
            }
        }
    
        // 3. keys with no values are still kept, even if empty
        // if the key is not present in $dataArray, its value from $list is used
        $result[$key] = $value;
    }
    

    If you move the if (! is_array($value)) block outside the if (array_key_exists()) block it will convert to arrays also the values of $list that are not arrays and are associated with keys that are not present in $dataArray (e.g $list['objects']). This way, after the code runs, all values of $result are arrays.


    Your code is good as well. Apart from iterating over $list and not over $dataArray, there is no way to make it faster or easier to read in a spectacular manner. The code I suggest here is just another way to write the same thing.