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;
}
}
}
2 Answers 2
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 callarray_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 thecountry_states
are in.
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!
0
. Does that help? \$\endgroup\$