Merge multiple multidimensional arrays by value
Problem
I have the following array, consisting of N
different services, where each entry consists of an identifier and a unique (user)name.
$input = [
'service_1' => [
'1234' => 'John_Doe_1',
'4567' => 'Jane Doe X',
'7891' => 'J.Doe1',
],
'service_2' => [
'100001' => 'Jane Doe X',
'100002' => 'John_Doe_1',
'100003' => 'J.Doe1',
],
'service_N' => [
'07faed21-2920-4d7d-a263-88deba9c422c' => 'John_Doe_1',
'1160178c-dfbf-4091-b4c0-a8ec55c22800' => 'J.Doe1',
],
];
Now I'm looking for a way to format it in a way that I get the identifiers across each (user)name for the different services:
$output = [
'John_Doe_1' => [
'service_1' => '1234',
'service_2' => '100002',
'service_N' => '07faed21-2920-4d7d-a263-88deba9c422c',
],
'Jane Doe X' => [
'service_1' => '4567',
'service_2' => '100001',
'service_N' => null, // either value should be null or key should not exist
],
'J.Doe1' => [
'service_1' => '7891',
'service_2' => '100003',
'service_N' => '1160178c-dfbf-4091-b4c0-a8ec55c22800',
],
];
I'm looking for a flexible way (with N
services) to do this but I can't come up with a good solution.
The code below should do the trick. This is how it works.
- Loops over the keys of the outer array to get the keys for the output array.
- Loops over the key value pair within every inner array.
- Creates an empty array in the output array with the username as key if it does not exist.
- Adds the 'ID' of the server under the name that we created earlier under the key it's currently looping through.
This should also still work within a reasonable time if your array input gets really big (e.g. 10000 elements).
$output = [];
// Loop over service_1, service_2, service_N etc.
foreach(array_keys($input) as $service_name)
{
// Loop over the inner key value pair (e.g. 10001 => John Doe X)
foreach($input[$service_name] as $service_id => $username)
{
// Create a key with the name if it does not exist in the output.
if(!isset($output[$username]))
{
$output[$username] = [];
}
// Add the key value pair to the correct output name.
$output[$username][$service_name] = $service_id;
}
}
That code will produce the following output.
Array
(
[John_Doe_1] => Array
(
[service_1] => 1234
[service_2] => 100002
[service_N] => 07faed21-2920-4d7d-a263-88deba9c422c
)
[Jane Doe X] => Array
(
[service_1] => 4567
[service_2] => 100001
)
[J.Doe1] => Array
(
[service_1] => 7891
[service_2] => 100003
[service_N] => 1160178c-dfbf-4091-b4c0-a8ec55c22800
)
)
I've been on a functional programming kick recently and figured I'd dive into PHP to see what I could come up with. Here's a nested array_walk
method that seems to do the trick!
$output = Array();
array_walk($input, function($item, $key) use (&$output) {
array_walk($item, function($item, $key, $parent_key) use (&$output) {
$output[$parent_key][$item] = $key;
}, $key);
});
var_dump($output);