Merge/Replace associative rows from one array with the associative rows of another array

1.7k views Asked by At

I have 2 arrays - one is hard coded and the other is data retrieved from a database. I am trying to merge them but I'm having unexpected results.

This is the first array:

$base_image_array = [
    ["product_image_one" => ""],
    ["product_image_two" => ""],
    ["product_image_three" => ""],
    ["product_image_four" => ""]
];

This is the second array:

$db_product_images = [
    ["product_image_one" => "../wp-content/themes/dosco/images/products_images/355_product_image_one.jpg"],
];

However, when I try array_merge($base_image_array, $db_product_images), I get 5 rows and the produce_image_one occurs more than once.

What I want to achieve is this:

[
    ['product_image_one' => '../wp-content/themes/dosco/images/products_images/355_product_image_one.jpg'],
    ['product_image_two' => ''],
    ['product_image_three' => ''],
    ['product_image_four' => '']
]

I think the multidimensional nature of the arrays is confusing me.

4

There are 4 answers

0
Matthew R. On

The problem is that the array keys in both arrays are numeric. If you want one array to overwrite the other you need to get them into a state where the array keys are strings. You could do something like this:

$array_with_four = array(...); // The large array
$new_array_with_four = format_arrays($array_with_four);

$array_with_one = array(...); // The small array
$new_array_with_one = format_arrays($array_with_one);

$merged = array_merge($new_array_with_four, $new_array_with_one); // Your new results

function format_arrays($array) {
    $return_array = array(); // Blank array
    foreach ($array as $child_key => $child_data){
        $return_array[$child_key] = $child_data;
    }
    return $return_array;
}

There are probably better ways to loop through this with the php array functions - but this should get the job done!

0
farmer1992 On

clean up your num indexed array to kv array

<?php

$base_image_array = array
(
 array("product_image_one" => ""),
 array("product_image_two" => ""),
 array("product_image_three" => ""),
 array("product_image_four" => "")
);

$db_product_images = array
(
 array("product_image_one" => "../wp-content/themes/dosco/images/products_images/355_product_image_one.jpg"),
);

function kv($a){
    $keys = array_map(current, array_map(array_keys, $a));
    $values = array_map(current, array_map(array_values, $a));

    return array_combine($keys, $values);
}

$base_image_array  = kv($base_image_array);
$db_product_images = kv($db_product_images);

$new_array = array_merge($base_image_array, $db_product_images);
print_r($new_array);

output

Array
(
    [product_image_one] => ../wp-content/themes/dosco/images/products_images/355_product_image_one.jpg
    [product_image_two] =>
    [product_image_three] =>
    [product_image_four] =>
)
0
jagershark On

The solution was very similar to the answer by @Matthew R.

/* Base Array */
$base_image_array = array(
    array('product_image_one' => ''),
    array('product_image_two' => ''),
    array('product_image_three' => ''),
    array('product_image_four' => '')
);

/* Populated Array */
$db_product_images = array(
    array("product_image_one" => "../wp-content/themes/dosco/images/products_images/355_product_image_one.jpg")
);

function format_array($array) {
    $return_array = array();
    foreach ($array as $key => $value) {
        foreach ($value as $k => $v) {
            $return_array[$k] = $v;
        }
    }
    return $return_array;
}

$array1 = format_array($base_image_array);
$array2 = format_array($db_product_images);

$final_array = array_merge($array1, $array2);

echo '<pre>';
    print_r($final_array);
echo '</pre>';

The resulting output was like so:

Array
(
    [product_image_one] => ../wp-content/themes/dosco/images/products_images/355_product_image_one.jpg
    [product_image_two] => 
    [product_image_three] => 
    [product_image_four] => 
)

The final output was actually different to what I originally thought I needed.

0
mickmackusa On

I recommend directly flattening the result because assuming these subarray keys are unique, there is no benefit to the depth of the data structure. You can unpack the two arrays with ... (spread operator) and feed the individualized row data to array_replace() (or array_merge()) to achieve the same conceptual result:

Code: (Demo)

var_export(array_replace(...$base_image_array, ...$db_product_images));

Output:

array (
  'product_image_one' => '../wp-content/themes/dosco/images/products_images/355_product_image_one.jpg',
  'product_image_two' => '',
  'product_image_three' => '',
  'product_image_four' => '',
)

If you desperately need to keep the deep structure, you can recreate the initial depth by mapping every associative element as its own row.

var_export(
    array_map(
        fn($v) => (array) $v,
        array_replace(...$base_image_array, ...$db_product_images)
    )
);