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);

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
8.5.90.0100.00816.86
8.5.80.0050.01316.86
8.5.70.0020.00516.83
8.5.60.0100.00816.71
8.5.50.0100.00818.57
8.5.30.0120.00617.67
8.5.20.0150.00317.86
8.5.10.0110.00716.77
8.5.00.0140.01021.85
8.4.230.0150.00819.71
8.4.220.0060.00519.80
8.4.210.0130.00819.74
8.4.180.0090.01319.70
8.4.170.0180.01020.57
8.4.160.0150.01023.96
8.4.150.0060.00216.89
8.4.140.0130.00817.39
8.4.130.0090.00918.62
8.4.120.0040.00524.11
8.4.110.0120.00818.86
8.4.100.0130.00818.76
8.4.90.0080.01220.66
8.4.80.0090.01118.67
8.4.70.0070.01518.77
8.4.60.0150.00518.71
8.4.50.0120.00718.66
8.4.40.0060.00317.73
8.4.30.0100.01020.23
8.4.20.0110.00617.90
8.4.10.0090.00019.35
8.3.320.0050.00518.60
8.3.310.0080.01218.62
8.3.300.0120.01020.79
8.3.290.0090.01320.74
8.3.280.0120.00918.22
8.3.270.0140.00716.75
8.3.260.0070.01316.86
8.3.250.0120.00719.06
8.3.240.0100.00917.05
8.3.230.0140.00716.80
8.3.220.0090.00918.83
8.3.210.0090.00916.52
8.3.200.0050.00416.71
8.3.190.0050.00317.34
8.3.180.0070.00818.83
8.3.170.0100.01016.94
8.3.160.0070.01117.14
8.3.150.0100.01019.22
8.3.140.0060.00317.34
8.3.130.0090.00018.41
8.3.120.0140.00718.80
8.3.110.0040.01120.94
8.3.100.0070.01324.06
8.3.90.0000.00826.77
8.3.80.0040.00416.88
8.3.70.0000.01616.88
8.3.60.0070.01418.56
8.3.50.0100.00923.56
8.3.40.0060.00921.90
8.3.30.0120.00618.84
8.3.20.0090.00024.18
8.3.10.0030.00624.66
8.3.00.0000.00926.16
8.2.320.0110.00918.05
8.2.310.0140.00818.16
8.2.300.0130.00722.12
8.2.290.0050.00420.77
8.2.280.0110.00818.23
8.2.270.0160.00316.64
8.2.260.0090.00916.68
8.2.250.0040.00416.66
8.2.240.0030.00617.05
8.2.230.0030.00922.58
8.2.220.0150.00437.54
8.2.210.0140.00026.77
8.2.200.0030.00616.63
8.2.190.0070.01116.75
8.2.180.0100.01025.92
8.2.170.0070.00719.08
8.2.160.0130.00322.96
8.2.150.0050.00225.66
8.2.140.0080.00024.66
8.2.130.0040.00426.16
8.2.120.0080.00026.35
8.2.110.0090.00020.52
8.2.100.0000.01117.84
8.2.90.0040.00417.91
8.2.80.0000.00919.46
8.2.70.0050.00317.63
8.2.60.0060.00317.63
8.2.50.0050.00317.63
8.2.40.0050.00518.03
8.2.30.0000.00818.02
8.2.20.0000.00718.15
8.2.10.0070.00019.23
8.2.00.0060.00319.38
8.1.340.0100.01219.48
8.1.330.0080.01021.92
8.1.320.0090.00917.72
8.1.310.0150.00317.81
8.1.300.0090.00918.43
8.1.290.0060.00318.88
8.1.280.0080.00825.92
8.1.270.0030.00523.99
8.1.260.0040.00428.09
8.1.250.0040.00428.09
8.1.240.0060.00321.02
8.1.230.0040.00820.93
8.1.220.0000.00817.76
8.1.210.0090.00018.77
8.1.200.0090.00017.48
8.1.190.0060.00317.35
8.1.180.0060.00318.10
8.1.170.0040.00418.74
8.1.160.0050.00218.85
8.1.150.0040.00418.93
8.1.140.0040.00420.66
8.1.130.0050.00220.18
8.1.120.0080.00017.56
8.1.110.0000.01017.51
8.1.100.0040.00417.49
8.1.90.0000.00717.38
8.1.80.0040.00417.50
8.1.70.0000.00717.55
8.1.60.0060.00317.61
8.1.50.0020.00817.46
8.1.40.0080.00117.52
8.1.30.0020.00717.58
8.1.20.0010.00817.61
8.1.10.0120.00117.49
8.1.00.0100.00617.29
8.0.300.0040.00420.11
8.0.290.0060.00316.88
8.0.280.0030.00318.55
8.0.270.0000.00818.10
8.0.260.0030.00318.54
8.0.250.0000.00816.98
8.0.240.0070.00316.89
8.0.230.0100.00016.98
8.0.220.0030.00316.93
8.0.210.0030.00316.92
8.0.200.0000.00717.01
8.0.190.0030.00516.85
8.0.180.0060.00816.80
8.0.170.0030.00816.84
8.0.160.0030.00716.80
8.0.150.0030.00816.80
8.0.140.0090.00516.75
8.0.130.0080.00314.92
8.0.120.0100.00416.69
8.0.110.0070.00616.72
8.0.100.0110.00416.70
8.0.90.0090.00516.72
8.0.80.0070.00916.80
8.0.70.0110.00316.78
8.0.60.0100.00416.72
8.0.50.0050.00816.56
8.0.30.0050.00916.99
8.0.20.0130.00716.89
8.0.10.0120.00216.84
8.0.00.0120.00416.75
7.4.330.0000.00515.55
7.4.320.0030.00316.64
7.4.300.0030.00316.52
7.4.290.0070.00316.44
7.4.280.0100.00416.42
7.4.270.0090.00216.44
7.4.260.0050.00814.70
7.4.250.0090.00316.40
7.4.240.0080.00616.40
7.4.230.0090.00316.57
7.4.220.0070.00316.54
7.4.210.0070.01016.51
7.4.200.0090.00216.35
7.4.190.0070.00716.41
7.4.180.0060.00716.63
7.4.160.0130.00216.37
7.4.150.0100.00315.70
7.4.140.0170.00015.82
7.4.130.0160.00716.28
7.4.120.0210.00416.32
7.4.110.0190.00516.34
7.4.100.0180.00716.30
7.4.90.0190.00716.47
7.4.80.0170.00816.35
7.4.70.0170.00716.23
7.4.60.0210.00416.27
7.4.50.0150.00916.33
7.4.40.0210.00616.15
7.4.30.0070.01316.35
7.4.20.0150.00916.46
7.4.10.0160.00816.42
7.4.00.0150.00816.45
7.3.330.0120.00316.31
7.3.320.0110.00314.96
7.3.310.0080.00616.44
7.3.300.0100.00316.32
7.3.290.0100.00616.37
7.3.280.0220.00016.50
7.3.270.0100.01016.21
7.3.260.0200.00516.47
7.3.250.0230.00416.49
7.3.240.0190.00716.48
7.3.230.0170.00916.41
7.3.220.0160.01016.53
7.3.210.0210.00416.32
7.3.200.0200.00916.41
7.3.190.0210.00516.33
7.3.180.0200.00416.44
7.3.170.0230.00616.48
7.3.160.0240.00216.44
7.3.150.0160.00916.52
7.3.140.0170.01016.51
7.3.130.0190.00616.29
7.3.120.0180.01016.40
7.3.110.0230.00416.45
7.3.100.0150.00916.38
7.3.90.0120.00816.28
7.3.80.0150.00816.19
7.3.70.0120.00916.21
7.3.60.0180.00316.34
7.3.50.0140.00516.11
7.3.40.0190.00516.38
7.3.30.0200.00516.54
7.3.20.0310.00517.26
7.3.10.0170.00817.36
7.3.00.0200.00717.34
7.2.340.0140.01216.48
7.2.330.0200.00916.63
7.2.320.0170.00816.54
7.2.310.0100.01416.58
7.2.300.0180.00716.57
7.2.290.0200.00816.49
7.2.280.0160.00916.46
7.2.270.0200.00416.50
7.2.260.0180.00616.61
7.2.250.0180.00916.62
7.2.240.0240.00416.57
7.2.230.0120.01116.26
7.2.220.0150.00716.32
7.2.210.0170.00616.49
7.2.200.0120.01016.38
7.2.190.0140.00716.51
7.2.180.0150.00616.33
7.2.170.0170.00716.71
7.2.160.0180.00716.68
7.2.150.0870.00817.62
7.2.140.0130.01117.54
7.2.130.0180.00817.63
7.2.120.0190.00617.64
7.2.110.0190.00717.50
7.2.100.0180.00817.56
7.2.90.0220.00417.54
7.2.80.0200.00618.38
7.2.70.0180.00718.50
7.2.60.0200.00518.55
7.2.50.0180.00618.41
7.2.40.0230.00318.53
7.2.30.0160.01018.41
7.2.20.0140.01118.51
7.2.10.0180.01218.49
7.2.00.0200.00918.46

preferences:
59.1 ms | 1793 KiB | 5 Q