3v4l.org

run code in 500+ PHP versions simultaneously
<?php $rows[] = [ "widget_id" => "widget1", "size" => "large", "item" => [ "item_id" => "item1", "shape" => "circle", "paint" => [ "paint_id" => "paint1", "colour" => "red", ] ] ]; # Exactly the same as above, except the "paint" child array is different $rows[] = [ "widget_id" => "widget1", "size" => "large", "item" => [ "item_id" => "item1", "shape" => "circle", "paint" => [ "paint_id" => "paint2", "colour" => "green", ] ] ]; # Same children ("item" and "paint") as the first row, but different parents ("widget_id" is different) $rows[] = [ "widget_id" => "widget2", "size" => "medium", "item" => [ "item_id" => "item1", "shape" => "circle", "paint" => [ "paint_id" => "paint1", "colour" => "red", ] ] ]; class ComplexMerge{ /** * Checks to see whether an array has sequential numerical keys (only), * starting from 0 to n, where n is the array count minus one. * * @link https://codereview.stackexchange.com/questions/201/is-numeric-array-is-missing/204 * * @param $arr * * @return bool */ private static function isNumericArray($arr) { if(!is_array($arr)){ return false; } return array_keys($arr) === range(0, (count($arr) - 1)); } /** * Given an array, separate out * array values that themselves are arrays * and those that are not. * * @param array $array * * @return array[] */ private static function separateOutArrayValues(array $array): array { $valuesThatAreArrays = []; $valuesThatAreNotArrays = []; foreach($array as $key => $val){ if(is_array($val)){ $valuesThatAreArrays[$key] = $val; } else { $valuesThatAreNotArrays[$key] = $val; } } return [$valuesThatAreArrays, $valuesThatAreNotArrays]; } /** * Groups row keys together that have the same non-array values. * If every row is already unique, returns NULL. * * @param $array * * @return array|null */ private static function groupRowKeysWithSameNonArrayValues($array): ?array { foreach($array as $key => $row){ # Separate out the values that are arrays and those that are not [$a, $v] = self::separateOutArrayValues($row); # Serialise the values that are not arrays and create a unique ID from them $uniqueRowId = md5(serialize($v)); # Store all the original array keys under the unique ID $deduplicatedArray[$uniqueRowId][] = $key; } # If every row is unique, there are no more rows to combine, and our work is done if(!$a && count($array) == count($deduplicatedArray)){ return NULL; } return $deduplicatedArray; } private static function mergeRows(array $array): array { # Get the grouped row keys if(!$groupedRowKeys = self::groupRowKeysWithSameNonArrayValues($array)){ //If there are no more rows to merge return $array; } foreach($groupedRowKeys as $uniqueRowId => $keys){ foreach($keys as $id => $key){ # Separate out the values that are arrays and those that are not [$valuesThatAreArrays, $valuesThatAreNotArrays] = self::separateOutArrayValues($array[$key]); //We're using the key from the grouped row keys array, but using it on the original array # If this is the first row from the group, throw in the non-array values if(!$id){ $unique[$uniqueRowId] = $valuesThatAreNotArrays; } # For each of the values that are arrays include them back in foreach($valuesThatAreArrays as $k => $childArray){ $unique[$uniqueRowId][$k][] = $childArray; //Wrap them in a numerical key array so that only children and siblings are have the same parent-child relationship } } } # Go deeper foreach($unique as $key => $val){ foreach($val as $k => $valuesThatAreNotArrays){ if(self::isNumericArray($valuesThatAreNotArrays)){ $unique[$key][$k] = self::mergeRows($unique[$key][$k]); } } } # No need to include the unique row IDs return array_values($unique); } public static function normalise($array): ?array { $array = self::mergeRows($array); return $array; } } $array = ComplexMerge::normalise($rows); var_export($array);
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/aYNeR
function name:  (null)
number of ops:  14
compiled vars:  !0 = $rows, !1 = $array
line      #* E I O op                               fetch          ext  return  operands
-----------------------------------------------------------------------------------------
    3     0  E >   ASSIGN_DIM                                                   !0
    4     1        OP_DATA                                                      <array>
   17     2        ASSIGN_DIM                                                   !0
   18     3        OP_DATA                                                      <array>
   31     4        ASSIGN_DIM                                                   !0
   32     5        OP_DATA                                                      <array>
  165     6        INIT_STATIC_METHOD_CALL                                      'ComplexMerge', 'normalise'
          7        SEND_VAR                                                     !0
          8        DO_FCALL                                          0  $5      
          9        ASSIGN                                                       !1, $5
  167    10        INIT_FCALL                                                   'var_export'
         11        SEND_VAR                                                     !1
         12        DO_ICALL                                                     
         13      > RETURN                                                       1

Class ComplexMerge:
Function isnumericarray:
Finding entry points
Branch analysis from position: 0
2 jumps found. (Code = 43) Position 1 = 4, Position 2 = 5
Branch analysis from position: 4
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 5
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/aYNeR
function name:  isNumericArray
number of ops:  17
compiled vars:  !0 = $arr
line      #* E I O op                               fetch          ext  return  operands
-----------------------------------------------------------------------------------------
   55     0  E >   RECV                                                 !0      
   57     1        TYPE_CHECK                                      128  ~1      !0
          2        BOOL_NOT                                             ~2      ~1
          3      > JMPZ                                                         ~2, ->5
   58     4    > > RETURN                                                       <false>
   60     5    >   INIT_FCALL                                                   'array_keys'
          6        SEND_VAR                                                     !0
          7        DO_ICALL                                             $3      
          8        INIT_FCALL                                                   'range'
          9        SEND_VAL                                                     0
         10        COUNT                                                ~4      !0
         11        SUB                                                  ~5      ~4, 1
         12        SEND_VAL                                                     ~5
         13        DO_ICALL                                             $6      
         14        IS_IDENTICAL                                         ~7      $3, $6
         15      > RETURN                                                       ~7
   61    16*     > RETURN                                                       null

End of function isnumericarray

Function separateoutarrayvalues:
Finding entry points
Branch analysis from position: 0
2 jumps found. (Code = 77) Position 1 = 4, Position 2 = 14
Branch analysis from position: 4
2 jumps found. (Code = 78) Position 1 = 5, Position 2 = 14
Branch analysis from position: 5
2 jumps found. (Code = 43) Position 1 = 8, Position 2 = 11
Branch analysis from position: 8
1 jumps found. (Code = 42) Position 1 = 13
Branch analysis from position: 13
1 jumps found. (Code = 42) Position 1 = 4
Branch analysis from position: 4
Branch analysis from position: 11
1 jumps found. (Code = 42) Position 1 = 4
Branch analysis from position: 4
Branch analysis from position: 14
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 14
filename:       /in/aYNeR
function name:  separateOutArrayValues
number of ops:  21
compiled vars:  !0 = $array, !1 = $valuesThatAreArrays, !2 = $valuesThatAreNotArrays, !3 = $val, !4 = $key
line      #* E I O op                               fetch          ext  return  operands
-----------------------------------------------------------------------------------------
   72     0  E >   RECV                                                 !0      
   74     1        ASSIGN                                                       !1, <array>
   75     2        ASSIGN                                                       !2, <array>
   77     3      > FE_RESET_R                                           $7      !0, ->14
          4    > > FE_FETCH_R                                           ~8      $7, !3, ->14
          5    >   ASSIGN                                                       !4, ~8
   78     6        TYPE_CHECK                                      128          !3
          7      > JMPZ                                                         ~10, ->11
   79     8    >   ASSIGN_DIM                                                   !1, !4
          9        OP_DATA                                                      !3
   78    10      > JMP                                                          ->13
   81    11    >   ASSIGN_DIM                                                   !2, !4
         12        OP_DATA                                                      !3
   77    13    > > JMP                                                          ->4
         14    >   FE_FREE                                                      $7
   85    15        INIT_ARRAY                                           ~13     !1
         16        ADD_ARRAY_ELEMENT                                    ~13     !2
         17        VERIFY_RETURN_TYPE                                           ~13
         18      > RETURN                                                       ~13
   86    19*       VERIFY_RETURN_TYPE                                           
         20*     > RETURN                                                       null

End of function separateoutarrayvalues

Function grouprowkeyswithsamenonarrayvalues:
Finding entry points
Branch analysis from position: 0
2 jumps found. (Code = 77) Position 1 = 2, Position 2 = 23
Branch analysis from position: 2
2 jumps found. (Code = 78) Position 1 = 3, Position 2 = 23
Branch analysis from position: 3
1 jumps found. (Code = 42) Position 1 = 2
Branch analysis from position: 2
Branch analysis from position: 23
2 jumps found. (Code = 46) Position 1 = 26, Position 2 = 30
Branch analysis from position: 26
2 jumps found. (Code = 43) Position 1 = 31, Position 2 = 32
Branch analysis from position: 31
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 32
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 30
Branch analysis from position: 23
filename:       /in/aYNeR
function name:  groupRowKeysWithSameNonArrayValues
number of ops:  36
compiled vars:  !0 = $array, !1 = $row, !2 = $key, !3 = $a, !4 = $v, !5 = $uniqueRowId, !6 = $deduplicatedArray
line      #* E I O op                               fetch          ext  return  operands
-----------------------------------------------------------------------------------------
   96     0  E >   RECV                                                 !0      
   98     1      > FE_RESET_R                                           $7      !0, ->23
          2    > > FE_FETCH_R                                           ~8      $7, !1, ->23
          3    >   ASSIGN                                                       !2, ~8
  100     4        INIT_STATIC_METHOD_CALL                                      'separateOutArrayValues'
          5        SEND_VAR                                                     !1
          6        DO_FCALL                                          0  $10     
          7        FETCH_LIST_R                                         $11     $10, 0
          8        ASSIGN                                                       !3, $11
          9        FETCH_LIST_R                                         $13     $10, 1
         10        ASSIGN                                                       !4, $13
         11        FREE                                                         $10
  103    12        INIT_FCALL                                                   'md5'
         13        INIT_FCALL                                                   'serialize'
         14        SEND_VAR                                                     !4
         15        DO_ICALL                                             $15     
         16        SEND_VAR                                                     $15
         17        DO_ICALL                                             $16     
         18        ASSIGN                                                       !5, $16
  106    19        FETCH_DIM_W                                          $18     !6, !5
         20        ASSIGN_DIM                                                   $18
         21        OP_DATA                                                      !2
   98    22      > JMP                                                          ->2
         23    >   FE_FREE                                                      $7
  110    24        BOOL_NOT                                             ~20     !3
         25      > JMPZ_EX                                              ~20     ~20, ->30
         26    >   COUNT                                                ~21     !0
         27        COUNT                                                ~22     !6
         28        IS_EQUAL                                             ~23     ~21, ~22
         29        BOOL                                                 ~20     ~23
         30    > > JMPZ                                                         ~20, ->32
  111    31    > > RETURN                                                       null
  114    32    >   VERIFY_RETURN_TYPE                                           !6
         33      > RETURN                                                       !6
  115    34*       VERIFY_RETURN_TYPE                                           
         35*     > RETURN                                                       null

End of function grouprowkeyswithsamenonarrayvalues

Function mergerows:
Finding entry points
Branch analysis from position: 0
2 jumps found. (Code = 43) Position 1 = 7, Position 2 = 9
Branch analysis from position: 7
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 9
2 jumps found. (Code = 77) Position 1 = 10, Position 2 = 40
Branch analysis from position: 10
2 jumps found. (Code = 78) Position 1 = 11, Position 2 = 40
Branch analysis from position: 11
2 jumps found. (Code = 77) Position 1 = 13, Position 2 = 38
Branch analysis from position: 13
2 jumps found. (Code = 78) Position 1 = 14, Position 2 = 38
Branch analysis from position: 14
2 jumps found. (Code = 43) Position 1 = 26, Position 2 = 28
Branch analysis from position: 26
2 jumps found. (Code = 77) Position 1 = 29, Position 2 = 36
Branch analysis from position: 29
2 jumps found. (Code = 78) Position 1 = 30, Position 2 = 36
Branch analysis from position: 30
1 jumps found. (Code = 42) Position 1 = 29
Branch analysis from position: 29
Branch analysis from position: 36
1 jumps found. (Code = 42) Position 1 = 13
Branch analysis from position: 13
Branch analysis from position: 36
Branch analysis from position: 28
Branch analysis from position: 38
1 jumps found. (Code = 42) Position 1 = 10
Branch analysis from position: 10
Branch analysis from position: 38
Branch analysis from position: 40
2 jumps found. (Code = 77) Position 1 = 42, Position 2 = 62
Branch analysis from position: 42
2 jumps found. (Code = 78) Position 1 = 43, Position 2 = 62
Branch analysis from position: 43
2 jumps found. (Code = 77) Position 1 = 45, Position 2 = 60
Branch analysis from position: 45
2 jumps found. (Code = 78) Position 1 = 46, Position 2 = 60
Branch analysis from position: 46
2 jumps found. (Code = 43) Position 1 = 51, Position 2 = 59
Branch analysis from position: 51
1 jumps found. (Code = 42) Position 1 = 45
Branch analysis from position: 45
Branch analysis from position: 59
Branch analysis from position: 60
1 jumps found. (Code = 42) Position 1 = 42
Branch analysis from position: 42
Branch analysis from position: 60
Branch analysis from position: 62
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 62
Branch analysis from position: 40
filename:       /in/aYNeR
function name:  mergeRows
number of ops:  70
compiled vars:  !0 = $array, !1 = $groupedRowKeys, !2 = $keys, !3 = $uniqueRowId, !4 = $key, !5 = $id, !6 = $valuesThatAreArrays, !7 = $valuesThatAreNotArrays, !8 = $unique, !9 = $childArray, !10 = $k, !11 = $val
line      #* E I O op                               fetch          ext  return  operands
-----------------------------------------------------------------------------------------
  117     0  E >   RECV                                                 !0      
  120     1        INIT_STATIC_METHOD_CALL                                      'groupRowKeysWithSameNonArrayValues'
          2        SEND_VAR                                                     !0
          3        DO_FCALL                                          0  $12     
          4        ASSIGN                                               ~13     !1, $12
          5        BOOL_NOT                                             ~14     ~13
          6      > JMPZ                                                         ~14, ->9
  122     7    >   VERIFY_RETURN_TYPE                                           !0
          8      > RETURN                                                       !0
  125     9    > > FE_RESET_R                                           $15     !1, ->40
         10    > > FE_FETCH_R                                           ~16     $15, !2, ->40
         11    >   ASSIGN                                                       !3, ~16
  127    12      > FE_RESET_R                                           $18     !2, ->38
         13    > > FE_FETCH_R                                           ~19     $18, !4, ->38
         14    >   ASSIGN                                                       !5, ~19
  129    15        INIT_STATIC_METHOD_CALL                                      'separateOutArrayValues'
         16        FETCH_DIM_R                                          ~21     !0, !4
         17        SEND_VAL                                                     ~21
         18        DO_FCALL                                          0  $22     
         19        FETCH_LIST_R                                         $23     $22, 0
         20        ASSIGN                                                       !6, $23
         21        FETCH_LIST_R                                         $25     $22, 1
         22        ASSIGN                                                       !7, $25
         23        FREE                                                         $22
  133    24        BOOL_NOT                                             ~27     !5
         25      > JMPZ                                                         ~27, ->28
  134    26    >   ASSIGN_DIM                                                   !8, !3
         27        OP_DATA                                                      !7
  138    28    > > FE_RESET_R                                           $29     !6, ->36
         29    > > FE_FETCH_R                                           ~30     $29, !9, ->36
         30    >   ASSIGN                                                       !10, ~30
  139    31        FETCH_DIM_W                                          $32     !8, !3
         32        FETCH_DIM_W                                          $33     $32, !10
         33        ASSIGN_DIM                                                   $33
         34        OP_DATA                                                      !9
  138    35      > JMP                                                          ->29
         36    >   FE_FREE                                                      $29
  127    37      > JMP                                                          ->13
         38    >   FE_FREE                                                      $18
  125    39      > JMP                                                          ->10
         40    >   FE_FREE                                                      $15
  146    41      > FE_RESET_R                                           $35     !8, ->62
         42    > > FE_FETCH_R                                           ~36     $35, !11, ->62
         43    >   ASSIGN                                                       !4, ~36
  147    44      > FE_RESET_R                                           $38     !11, ->60
         45    > > FE_FETCH_R                                           ~39     $38, !7, ->60
         46    >   ASSIGN                                                       !10, ~39
  148    47        INIT_STATIC_METHOD_CALL                                      'isNumericArray'
         48        SEND_VAR                                                     !7
         49        DO_FCALL                                          0  $41     
         50      > JMPZ                                                         $41, ->59
  149    51    >   INIT_STATIC_METHOD_CALL                                      'mergeRows'
         52        FETCH_DIM_R                                          ~44     !8, !4
         53        FETCH_DIM_R                                          ~45     ~44, !10
         54        SEND_VAL                                                     ~45
         55        DO_FCALL                                          0  $46     
         56        FETCH_DIM_W                                          $42     !8, !4
         57        ASSIGN_DIM                                                   $42, !10
         58        OP_DATA                                                      $46
  147    59    > > JMP                                                          ->45
         60    >   FE_FREE                                                      $38
  146    61      > JMP                                                          ->42
         62    >   FE_FREE                                                      $35
  155    63        INIT_FCALL                                                   'array_values'
         64        SEND_VAR                                                     !8
         65        DO_ICALL                                             $47     
         66        VERIFY_RETURN_TYPE                                           $47
         67      > RETURN                                                       $47
  156    68*       VERIFY_RETURN_TYPE                                           
         69*     > RETURN                                                       null

End of function mergerows

Function normalise:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/aYNeR
function name:  normalise
number of ops:  9
compiled vars:  !0 = $array
line      #* E I O op                               fetch          ext  return  operands
-----------------------------------------------------------------------------------------
  158     0  E >   RECV                                                 !0      
  160     1        INIT_STATIC_METHOD_CALL                                      'mergeRows'
          2        SEND_VAR                                                     !0
          3        DO_FCALL                                          0  $1      
          4        ASSIGN                                                       !0, $1
  161     5        VERIFY_RETURN_TYPE                                           !0
          6      > RETURN                                                       !0
  162     7*       VERIFY_RETURN_TYPE                                           
          8*     > RETURN                                                       null

End of function normalise

End of class ComplexMerge.

Generated using Vulcan Logic Dumper, using php 8.5.0


preferences:
228.36 ms | 2458 KiB | 19 Q