2

To be short, I have two simple arrays and I want to verify if certain keys from the second array have empty values and replace them with their correspondent values from the first array.

Example:

$a1 = [ 1 => 'one', 2 => 'two', 3 => 'three',5=>'cinco', 6=>'six'];
$a2 = [ 2 => 'two', 5=>'five', 6=>'' ];

Result:

Array
(
    [2] => two
    [5] => five
    [6] => six
)

The following code works already for this.

$keys = array_keys($a1);
foreach ($keys as $k)
{
    if ((isset($a2[$k])) && (($a2[$k]) == '')) {
     $a2[$k] = $a1[$k];
    }
}
print_r($a2);

But what if we want to apply this for two 2D arrays? What will be the proper approach in that case? Let's say these two 2D arrays will be:

$superheroes_complete = array(
    "spiderman" => array(
        "name" => "Peter Parker",
        "email" => "[email protected]",
    ),
    "superman" => array(
        "name" => "Clark Kent",
        "email" => "[email protected]",
    ),
    "ironman" => array(
        "name" => "Harry Potter",
        "email" => "[email protected]",
    )
);

$superheroes_empty = array(
    "spiderman" => array(
        "name" => "Peter Parker",
        "email" => "",
    ),
    "superman" => array(
        "name" => "Clark Kent",
        "email" => "something",
    ),
    "ironman" => array(
        "name" => "Harry Potter",
        "email" => "another one",
    )
);

Expectation:

$superheroes = array(
    "spider-man" => array(
        "name" => "Peter Parker",
        "email" => "[email protected]",
    ),
    "super-man" => array(
        "name" => "Clark Kent",
        "email" => "something",
    ),
    "iron-man" => array(
        "name" => "Harry Potter",
        "email" => "another one",
    )
);

Much appreciation and thank you in advance!

0

6 Answers 6

1

You've added another level to your data, so you can just add another level to your checking as well with a second foreach loop:

foreach ($superheroes_complete as $hero => $info) {
    foreach ($info as $key => $value) {
        if (empty($superheroes_empty[$hero][$key])) {
            $superheroes_empty[$hero][$key] = $value;
        }
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

But what if we have the situation of having a simple array and a 2D array? The simple array: $superheroes_complete = array(1 => 'one', 2 => 'two', 3 => 'three', 5 => 'cinco', 6 => 'six', 'email' => '[email protected]'); The 2D array: $superheroes_empty = array( "spiderman" => array( "name" => "Peter Parker", "email" => "", ), "superman" => array( "name" => "Clark Kent", "email" => "something", ), "ironman" => array( "name" => "Harry Potter", "email" => "another one", ) );
I'm sure it would be doable, but it sounds different enough from what we've done here that it would probably be difficult to figure out in comments. If you post another question with some good examples of input and desired output like you did here, I'd be happy to show you how I would do it.
OK, I'll do a separate question and post the link here. Thank you for your time.
@dont-panic This is the link to the new article. Hope is better described. Thanks! stackoverflow.com/questions/38283252
1

First note that your 1D case can be simplified:

foreach ($a2 as $k => $v) {
  if (!isset($v)) {
    $a2[$k] = $a1[$k];
  }
}

Then for the 2D case, assuming the 1st level keys are always the same (or it becomes a quite different question!):

foreach ($superheroes_complete as $main_k => $main_v) {
  foreach ($main_v as $k => $v) {
    if (!isset($v)) {
      $superheroes_empty[$main_k][$k] = $superheroes_complete[$main_k][$k];
    }
  }

Comments

0

If you only need to take care of the "email" field you can do this :

<?php
$keys = array_keys($superheroes_complete);
foreach ($keys as $k)
{
    if ((isset($superheroes_empty[$k]["email"])) &&
        (($superheroes_empty[$k]["email"]) == '')) {
     $superheroes_empty[$k]["email"] = $superheroes_complete[$k]["email"];
    }
}
var_dump($superheroes_empty);
?>

Comments

0

For the generic case where the depth of nesting is unlimited, you could use this recursive function:

function fillEmpty(&$filled, &$empty) { // arguments are by reference
    if ($empty === "") {
        $empty = $filled;
        return;
    }
    if (!is_array($filled) || !is_array($empty)) return;
    foreach ($filled as $key => $value) {
        if (isset($empty[$key])) fillEmpty($value, $empty[$key]);
    }
}

Example call:

fillEmpty($superheroes_complete, $superheroes_empty);

This modifies the second argument, filling the empty values.

See it run on eval.in

Comments

0

It might be your lucky day, php has some built in functions to compare arrays values and keys. Use array_diff() which can compare two or more arrays and return the difference. You could also use array_intersect() which does the opposite.

If you want to only compare the keys, use array_diff_key()which returns only the key difference or array_intersect_key() which returns the matched keys.

1 Comment

I would love to see a solution using just the array_ functions. Without that code, this is more a comment then an answer imo...
0

You could also consider a recursive solution. This could work on both the 1D and 2D arrays, or even an array of N dimensions.

I'm aware that recursion should be used with care, as it can be quite resource intensive. This is however a more versatile solution, and keeps the code cleaner with less nested control structures and early returns, which I find better readable. I'll use the native array_walk method because I was taught that it should perform better then a php loop.

So this is what my code would look like:

function array_complement_recursive(&$partial, $complete) {
    array_walk($partial, function(&$value, $key) use ($complete) {
        // (for safety) complete does not contain matching key: done
        if (! array_key_exists($key, $complete)) {
            return;
        }

        // value is array: call recursive
        if (is_array($value)) {
            array_complement_recursive($value, $complete[$key]);
            return;
        }

        // value is not 'empty': done
        // note that null, 0, false will also not match, you may want to make
        // this check more specific to match only the empty string
        if ($value) {
            return;
        }

        $value = $complete[$key];
    });
}

I've set up a little demo so you can see that it works on both your examples. And as I said, it should even work for arrays with more dimensions, or a more irregular structure.

http://phpfiddle.org/main/code/49iz-vrwg

I've added some comments to explain, but feel free to ask if anything is unclear.

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.