suz
suz

Reputation: 747

PHP: merge multidimensional, associative arrays (LEFT JOIN simulation - keep duplicates, keep non-existent elements)

I got two associative, multidimensional arrays $arrayOffered and $arraySold. I would like to merge them under certain conditions:

One element from $arrayOffered can have >1 equivalents in $arraySold. They should be joined in the way shown below.

Input data:

$arrayOffered = array(
          0 => array('item' => 'product_1', 'Category' => 'ABC'), 
          1 => array('item' => 'product_2', 'Category' => 'DEF')
          );  

$arraySold = array(
          0 => array('item' => 'product_1', 'ItemsSold' => '2', 'ItemsReturned' => 1), //arrays in this array can contain up to 30 elements
          1 => array('item' => 'product_1', 'ItemsSold' => '1')
          );    

Desired result:

$desiredResult = array( 
        0 => array('item' => 'product_1', 'Category' => 'ABC', 'ItemsSold' => '2', 'ItemsReturned' => 1),
        1 => array('item' => 'product_1', 'Category' => 'ABC', 'ItemsSold' => '1'),
        2 => array('item' => 'product_2', 'Category' => 'DEF')
        );  

I got stuck on something like:

$result = array();
foreach ($arrayOffered as $keyOffered => $offeredSubArr)
{
    $item = $offeredSubArr['item'];
    foreach($arraySold as $keySold => $soldSubArr)
    {
        if(isset($soldSubArr['item']) && $soldSubArr['item'] == $item) 
        {   
            $i = 0;
            $test = array_merge($offeredSubArr, $soldSubArr);
            $result[$i][] = $test;
            $i++;
        }
        else 
        {
          $result[$i][] = $offeredSubArr;
          $i++;
        }
    }
}

Problem:
- output array isn't formatted the way I wanted
- I know I'm not going in the right direction. Can you please give me a hint?

Upvotes: 1

Views: 130

Answers (3)

dminones
dminones

Reputation: 2306

This is an option, since you have this $arrayOffered as a kind of master file I suggest to build a hash with this array and use later on the foreach look for sold array.

$arrayOffered = array(
          0 => array('item' => 'product_1', 'Category' => 'ABC'), 
          1 => array('item' => 'product_2', 'Category' => 'DEF')
          );  

$arraySold = array(
          0 => array('item' => 'product_1', 'ItemsSold' => '2', 'ItemsReturned' => 1), //arrays in this array can contain up to 30 elements
          1 => array('item' => 'product_1', 'ItemsSold' => '1')
          );

//Build a hash to get the extra properties
$hashArray = array();
foreach ($arrayOffered as $offered) {
    $hashArray[$offered['item']]=$offered;
}

$resultArray = array();
foreach ($arraySold as $sold) {
    $hashItem = $hashArray[$sold['item']];  
    // you dont want this sold flag on your final result
    unset($hashItem['sold']);
    $resultArray[]=array_merge($hashItem,$sold);
    $hashArray[$sold['item']]['sold']= true;
}
//Add all the missing hash items
foreach($hashArray as $hashItem){
    if(!isset($hashItem['sold'])){
        $resultArray[]=$hashItem; 
    }
}
print_r($resultArray);  

Test sample http://sandbox.onlinephpfunctions.com/code/f48ceb3deb328088209fbaef4f01d8d4430478db

Upvotes: 2

Akis
Akis

Reputation: 178

Well i will try to follow your logic although there is simpler solutions. First of all we will need to search in a multidimentional array thats why we will need the followed function from this so thread

function in_array_r($needle, $haystack, $strict = false) {
    foreach ($haystack as $item) {
        if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
           return true;
        }
     }
     return false;
 }

Next after small changes:

  • $i you don't need to make it zero on every loop just once so place it outside
  • unnecessary [] ($result[$i][]) you don't need the empty brackets no reason to create an extra table in the $i row since what you add there, the $test is already table itself
  • Adding the last loop coz when sth is not in the second table it will be added in your new table in every loop and as far as i get you don't want that kind of duplicates

We have the following code:

 $arrayOffered = array(
      0 => array('item' => 'product_1', 'Category' => 'ABC'), 
      1 => array('item' => 'product_2', 'Category' => 'DEF')
      );  

 $arraySold = array(
      0 => array('item' => 'product_1', 'ItemsSold' => '2', 'ItemsReturned' => 1), //arrays in this array can contain up to 30 elements
      1 => array('item' => 'product_1', 'ItemsSold' => '1')
      );
 $i = 0;
 $result = array();
 foreach ($arrayOffered as $keyOffered => $offeredSubArr)
 {
     $item = $offeredSubArr['item'];
     foreach($arraySold as $keySold => $soldSubArr)
     {
          if(isset($soldSubArr['item']) && $soldSubArr['item'] == $item) 
          {   
               $test = array_merge($offeredSubArr, $soldSubArr);
               $result[$i] = $test;
               $i++;
          }
     }
}
foreach ($arrayOffered as $value)
{
     if (!in_array_r($value['item'], $result))
     {
          $result[$i] = $value;
          $i++;
     }
 }
 print_r($result);

Which as far as i tested gives the wanted result.

Upvotes: 1

Kartik Patel
Kartik Patel

Reputation: 310

$result = array();
            foreach ($arrayOffered as $keyOffered => $offeredSubArr)
            {
                $item = $offeredSubArr['item'];
                foreach($arraySold as $keySold => $soldSubArr)
                { $i = 0;
                    if(isset($soldSubArr['item']) && $soldSubArr['item'] == $item) 
                    {   

                        $test = array_merge($offeredSubArr, $soldSubArr);                       
                        $result[$i][] = $test;

                    }
                    else 
                    {

                        $result[$i][] = $offeredSubArr;                   

                    }


                    $i++;
                }
            }
            $result = $result[0];
            echo '<pre>'; print_r($result); die();

Upvotes: 1

Related Questions