How can I preserve multidimensional array information when performing array intersections in PHP?

StackOverflow https://stackoverflow.com/questions/10458370

  •  05-06-2021
  •  | 
  •  

Question

I have many arrays containing an ID as the primary key, with multidimensional information under each id. Here are two examples:

First Example Array:

array
  14181 => 
    array
      'industries' => 
        array
          'weight' => string '105652' (length=6)
          'count' => string '11' (length=2)
  48354 => 
    array
      'industries' => 
        array
          'weight' => string '508866' (length=6)
          'count' => string '10' (length=2)

Second Example Array:

array
  16434 => 
    array
      'business_types' => 
        array
          'weight' => string '104614' (length=6)
          'count' => string '1' (length=1)
  48354 => 
    array
      'business_types' => 
        array
          'weight' => string '103610' (length=6)
          'count' => string '10' (length=2)

I'd like to get the intersection of many arrays like these ( based on the key ), but I need to preserve the weight and count data from each array for each key. Notice it's different weight and count data from each array. In this case, business_type and industries.

Final Array Needed:

array
  48354 => 
    array
      'business_types' => 
        array
          'weight' => string '103610' (length=6)
          'count' => string '10' (length=2)
      'industries' => 
        array
          'weight' => string '508866' (length=6)
          'count' => string '10' (length=2)

Originally I was not trying to keep the weights and counts, so I was simply performing an array_intersect_keys() and the job was done. Now I need to keep this data. I named the sub arrays different things in the hope that array_intersect_keys() would preserve it, however, it only preserves it for the first array in the function.

Is there a preferred way to do something like this?

The only solution I can come up with is to reduce all the arrays to a list of final ID's ( keys ) and then loop through that array pulling the weight and count info from each of the original arrays we compared.

Was it helpful?

Solution

Your proposed solution seems fine, but you might consider merging one list into the other, e.g.

<?php

$a1 = array(14181 => array('industries'     => array('weight' => "105652", 'count' => "11")),
            48354 => array('industries'     => array('weight' => "508866", 'count' => "10")));
$a2 = array(16434 => array('business_types' => array('weight' => "104614", 'count' => "1")),
            48354 => array('business_types' => array('weight' => "103610", 'count' => "10")));

//print_r($a1);
//print_r($a2);

foreach($a2 as $a2k => $a2v)
{
    // The loop below should only go through once, but if there are multiple types it will be ok
    foreach($a2v as $a2vk => $a2vv)
    {
        $a1[$a2k][$a2vk] = $a2vv;
    }
}

printf("Output:\n");
print_r($a1);

printf("Output:\n");
print_r($a1);

Output:

Output:
Array
(
    [14181] => Array
        (
            [industries] => Array
                (
                    [weight] => 105652
                    [count] => 11
                )

        )

    [48354] => Array
        (
            [industries] => Array
                (
                    [weight] => 508866
                    [count] => 10
                )

            [business_types] => Array
                (
                    [weight] => 103610
                    [count] => 10
                )

        )

    [16434] => Array
        (
            [business_types] => Array
                (
                    [weight] => 104614
                    [count] => 1
                )

        )

)

I believe that this will be slightly faster than your proposed solution.


Edit: The above was an array merge type algorithm that would merge the arrays even if a key wasn't common among the arrays. The algorithm below will only produce the intersection of the two arrays. My fault in initially getting the question:

<?php

$a1 = array(14181 => array('industries'     => array('weight' => "105652", 'count' => "11")),
            48354 => array('industries'     => array('weight' => "508866", 'count' => "10")));
$a2 = array(16434 => array('business_types' => array('weight' => "104614", 'count' => "1")),
            48354 => array('business_types' => array('weight' => "103610", 'count' => "10")));

//print_r($a1);
//print_r($a2);

// Pass the smaller array as first argument
if(count($a1) <= count($a2))
{
    $res = my_merge($a1, $a2);
}
else
{
    $res = my_merge($a2, $a1);
}

function my_merge($a1, $a2)
{
    $res = array();
    foreach($a1 as $a1k => $a1v)
    {
        if(array_key_exists($a1k, $a2))
        {
            $res[$a1k] = array_merge($a1[$a1k], $a2[$a1k]);
        }
    }
    return $res;
}

printf("Output:\n");
print_r($res);

Output:

Array
(
    [48354] => Array
        (
            [industries] => Array
                (
                    [weight] => 508866
                    [count] => 10
                )

            [business_types] => Array
                (
                    [weight] => 103610
                    [count] => 10
                )

        )

)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top