4
\$\begingroup\$

I have an associative array of the states of some country, and the states names are the keys:

array:13 [
  "Ontario" => null
  "Manitoba" => null
  "New Brunswick" => null
  "Yukon" => null
  "Saskatchewan" => null
  "Prince Edward Island" => null
  "Alberta" => null
  "Quebec" => null
  "Nova Scotia" => null
  "British Columbia" => null
  "Nunavut" => null
  "Newfoundland and Labrador" => null
  "Northwest Territories" => null
] 

And I have anothe associative array that contains all states that have values:

array:8 [
  "Alberta" => 17
  "Cairo" => 1
  "Calgary" => 1
  "ddd" => 4
  "gfdxf" => 1
  "New Cairo" => 1
  "Ontario" => 1
  "secret" => 30
] 

Now I need to map the second array to the first one so that the result would be:

array:13 [
  "Ontario" => 1
  "Manitoba" => 0
  "New Brunswick" => 0
  "Yukon" => 0
  "Saskatchewan" => 0
  "Prince Edward Island" => 0
  "Alberta" => 17
  "Quebec" => 0
  "Nova Scotia" => 0
  "British Columbia" => 0
  "Nunavut" => 0
  "Newfoundland and Labrador" => 0
  "Northwest Territories" => 0
] 

I created a nested loop and it works fine, but the code is very ugly, now is there a more efficent way to do it?

My code:

foreach ($all_states as $state_x => $value_x) {

    foreach ($country_states as $state_y => &$value_y) {

        if (strtolower($state_x) == strtolower($state_y)) {

            $value_y = $value_x;
        } elseif ($value_y == NULL) {

            $value_y = 0;
        }
    }
}
\$\endgroup\$
3
  • \$\begingroup\$ What is it you want to review, there isn't a lot of code here to review? \$\endgroup\$
    – pacmaninbw
    Jan 9, 2020 at 16:08
  • \$\begingroup\$ In RDBS terms, that looks like a left join with a default of 0. Does that help? \$\endgroup\$ Jan 9, 2020 at 18:21
  • 1
    \$\begingroup\$ @pacmaninbw Sometimes there simply isn't more to it. It would be preferable to see how the result of this operation is used as well, but afar from that, it's close enough to be reviewable. \$\endgroup\$
    – Mast
    Jan 13, 2020 at 10:25

2 Answers 2

2
\$\begingroup\$

array_replace() is the perfect call here -- it can be used to overwrite the master array with the array containing actual integer values.

Code: (Demo)

var_export(array_replace(array_map('intval', $all_states), $country_states));

To streamline the process futher, you should declare your master list with 0 values instead of null values, then you can omit the array_map() call like this:

Code: (Demo)

var_export(array_replace($all_states, $country_states));

Additional suggestions, caveats, and considerations:

  • You might reconsider your variable names, as they don't seem to do a great job of describing the data that they contain. $all_states might be $statesLookup or $statesDefault. I don't know what is being counted in the second array, but $country_states might be better declared as $state_counts or something.
  • If $country_states has any elements with keys that are not represented in $all_states, then these new elements WILL be appended to the end of the output array. If this is a legitimate concern, you can call array_intersect_key($country_states, $all_states) to filter out any expected elements.
  • The order of the elements in the output array will be ordered by $all_states. No matter what order the country_states are in.
\$\endgroup\$
0
\$\begingroup\$

There is no reason for the multiple nested foreach loops as the keys are the same. Therefore, we can reduce the need for a second iterator, which can be slow. Also, we can simplify the statement by making use of the null coalescing operator.

$results = [];
foreach ($country_all as $key => $value) {
    $results[$key] = $country_values[$key] ?? 0;
}
var_dump($results);

Using your data.

$country_all = [
    "Ontario" => null,
    "Manitoba" => null,
    "New Brunswick" => null,
    "Yukon" => null,
    "Saskatchewan" => null,
    "Prince Edward Island" => null,
    "Alberta" => null,
    "Quebec" => null,
    "Nova Scotia" => null,
    "British Columbia" => null,
    "Nunavut" => null,
    "Newfoundland and Labrador" => null,
    "Northwest Territories" => null
];

$country_values = [
    "Alberta" => 17,
    "Cairo" => 1,
    "Calgary" => 1,
    "ddd" => 4,
    "gfdxf" => 1,
    "New Cairo" => 1,
    "Ontario" => 1,
    "secret" => 30
];

I hope this helps!

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.