3

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.

T. Brian Jones
  • 13,002
  • 25
  • 78
  • 117

1 Answers1

0

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
                )

        )

)
jedwards
  • 29,432
  • 3
  • 65
  • 92
  • How would you then reduce the combined array to just ID's ( and sub-arrays ) that were in all the original arrays ... or, in this case, to ID's that have both industries and business_type weights and counts? – T. Brian Jones May 05 '12 at 03:14
  • I edited my post and added an intersection algorithm instead of a merge algorithm. Yes, you could use the merge and then reduce it, but I think the approach I used in the edit would be faster. – jedwards May 05 '12 at 03:21