Home > front end >  Merge multiple multidimensional arrays by value
Merge multiple multidimensional arrays by value

Time:01-16

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.

CodePudding user response:

The code below should do the trick. This is how it works.

  1. Loops over the keys of the outer array to get the keys for the output array.
  2. Loops over the key value pair within every inner array.
  3. Creates an empty array in the output array with the username as key if it does not exist.
  4. 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
        )

)

CodePudding user response:

You need iteration to exist input array and format it.

$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',
    ],
];

// get all keys
$allKeys = array_keys($input);

$newArray = [];
// re-format array
foreach($input as $service => $record){
    foreach($record as $k=> $user){
        $newArray[$user][$service] = $k;
    }
}

// add all missing key(s)
foreach($newArray as &$record){ // &$record - please refer attached link
    $missingKeys = array_diff($allKeys, array_keys($record));
    if(!empty($missingKeys)){
        foreach($missingKeys as $key){
            $record[$key] = null;
        }
    }
}

echo '<pre>'; print_r($newArray);

Output:

 <pre>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
                [service_N] => 
            )
    
        [J.Doe1] => Array
            (
                [service_1] => 7891
                [service_2] => 100003
                [service_N] => 1160178c-dfbf-4091-b4c0-a8ec55c22800
            )
    
    )

Link: PHP "&" operator

CodePudding user response:

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);

CodePudding user response:

What are you asking? Seems like you need to walk across the entire structure. Create a new array and for each username search if exists an entry, if not create one, obtain the inner array of services and push the proper service and identifier.

  •  Tags:  
  • Related