skip to Main Content

I want to merge a multidimensional array values if the values are the same under the ‘u’,’v’ and ‘w’ keys.

$myarray = array (
  '0' => 
    array (
      'u' => '30', 
      'v' => '16', 
      'w' => '22',        
      'x' => '30', 
      'y' => '16', 
      'z' => '22',  
),
  '1' => 
    array (
      'u' => '32', 
      'v' => '25', 
      'w' => '1',        
      'x' => '30', 
      'y' => '16', 
      'z' => '22',
),   
  '2' => 
    array (
      'u' => '30', 
      'v' => '16', 
      'w' => '22',        
      'x' => '54', 
      'y' => '96', 
      'z' => '2',
),   
  '3' => 
    array (
      'u' => '30', 
      'v' => '16', 
      'w' => '22',        
      'x' => '3', 
      'y' => '1', 
      'z' => '6',
)    
); 

I want the output to be as below:

//OUTPUT

array (
  '0' => 
    array (
      'u' => '30', 
      'v' => '16', 
      'w' => '22',        
      'x' => '30,54,3', 
      'y' => '16,96,1', 
      'z' => '22,2,6',  
),
  '1' => 
    array (
      'u' => '32', 
      'v' => '25', 
      'w' => '1',        
      'x' => '30', 
      'y' => '16', 
      'z' => '22',
)   
) 

This is what I have tried to do so far, which has not worked out for me.

<?php
$n = 0;            
$output = [];
foreach ($myarray as $row) {
    
    $prevkey = key(array_slice($output, -1,1,true));// get previous array key    
    
    if(array_key_exists('0', $output)){
        
        if($output[$prevkey]['u'] == $row['u'] && $output[$prevkey]['v'] == $row['v'] &&   $output[$prevkey]['w'] == $row['w'] ){
            echo "yes <br>";
           $output += $row;
        }
        
    }else{
      $output[] = $row;  
    }
    $n++;
}

var_dump($output); 
?>

3

Answers


  1. You can create some specific array for that purpose with its specific indexes, based on those 3 values. For ex.:

    $myarray = [...];
    
    $supp = [];
    foreach ($myarray as $ind => $arr){
    
        // remember 3 values and use them as a new index
        $uvw = sprintf('%d|%d|%d', $arr['u'], $arr['v'], $arr['w']); 
    
        if (!isset($supp[$uvw])){
            $supp[$uvw] = ['ind' => $ind, 'data' => $arr];
        } else {
             
            foreach($arr as $in => $new_val){ 
                foreach($supp[$uvw]['data'] as $i => &$val){
                    if ($i === $in && !in_array($i,['u','v','w'])){
                        $val .= ',' . $new_val;
                    }
                }
            }
        }
    }
    
    // recombine the output data (it also includes the parent index value)
    $output = [];
    foreach($supp as $arr_data){
        $output[$arr_data['ind']] = $arr_data['data'];
    }
    
    print_r($output);
    

    Output:

    Array
    (
        [0] => Array
            (
                [u] => 30
                [v] => 16
                [w] => 22
                [x] => 30,54,3
                [y] => 16,96,1
                [z] => 22,2,6
            )
    
        [1] => Array
            (
                [u] => 32
                [v] => 25
                [w] => 1
                [x] => 30
                [y] => 16
                [z] => 22
            )
    
    )
    

    Demo

    Login or Signup to reply.
  2. You can use array_reduce:

    $grouped = array_reduce($myarray, function ($result, $item) {
        $key = '';
        foreach (['u', 'v', 'w'] as $prop) {
            $key .= $item[$prop] . '_';
        }
        if (array_key_exists($key, $result)) {
            foreach (['x', 'y', 'z'] as $prop) {
                $result[$key][$prop] .= ',' . $item[$prop];
            }
        } else {
            $result[$key] = $item;
        }
        return $result;
    }, []);
    
    $result = array_values($grouped);
    

    Working example

    Login or Signup to reply.
  3. This grouping by multiple columns can be done in a single loop without needing to reindex at the end if reference variables are pushed into the result array.

    vsprintf() is an easy way to create a delimited string fron the first 3 values in each row — if you need to explicitly name the identifying keys because they are not reliably first in the rows, then you can manually access them to building the composite key.

    Concatenation is only performed if a group is encountered more than once.

    Code: (Demo)

    $result = [];
    foreach ($array as $row) {
        $key = vsprintf('%d_%d_%d', $row);
        if (!isset($ref[$key])){
            $ref[$key] = $row;
            $result[] = &$ref[$key];
        } else {
            $ref[$key]['x'] .= ',' . $row['x'];
            $ref[$key]['y'] .= ',' . $row['y'];
            $ref[$key]['z'] .= ',' . $row['z'];
        }
    }
    var_export($result);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search