NotionCommotion Posted June 27, 2020 Share Posted June 27, 2020 I have a sequential multidimensional array with many outer rows where all the inner arrays have the same number of elements as another sequential array which represents metadata of the first array's inner arrrays. $keys: ["time","system1_typeA","system2_typeA","system1_typeB","system3_typeC","system2_typeB","system1_typeC"] $arrayValues: [ ["2020-06-27 07:40:06",2.16,9.25,9.44,7.76,5.43,1.12], ["2020-06-27 07:40:23",2.66,8.93,4.31,6.59,8.44,3.42], ["2020-06-27 07:41:24",8.71,2.78,8.92,6.58,3.65,4.38], ["2020-06-27 07:41:58",1.86,6.36,2.65,3.99,7.25,3.32], ["2020-06-27 07:42:33",8.71,3.66,8.82,8.54,8.22,4.51] ] My desired output is: { "time": ["2020-06-27 07:40:06", "2020-06-27 07:40:23", "2020-06-27 07:41:24", "2020-06-27 07:41:58", "2020-06-27 07:42:33"], "system1": { "typeA": [2.16, 2.66, 8.71, 1.86, 8.71], "typeB": [9.44, 4.31, 8.92, 2.65, 8.82], "typeC": [1.12, 3.42, 4.38, 3.32, 4.51] }, "system2": { "typeA": [9.25, 8.93, 2.78, 6.36, 3.66], "typeB": [5.43, 8.44, 3.65, 7.25, 8.22] }, "system3": { "typeC": [7.76, 6.59, 6.58, 3.99, 8.54] } } Is there much faster way to do so than the following? I would like to use a built in function like array_combine() if possible, but grouping by system and type creates an issue. function transform(array $keys, array $arrayValues):array { $map=[]; foreach ($keys as $key) { $map[] = explode('_',$key); } $count=count($keys); $newValues=[]; foreach ($arrayValues as $i=>$arrayValue) { $newValues['time'][]=$arrayValue[0]; for ($i = 1; $i < $count; $i++) { $newValues[$map[$i][0]][$map[$i][1]][]=$arrayValue[$i]; } } return $newValues; } Quote Link to comment Share on other sites More sharing options...
requinix Posted June 27, 2020 Share Posted June 27, 2020 Want a hint? It's a pretty big one. array_fill_keys + array_map with array_combine + array_merge_recursive One-liner. Quote Link to comment Share on other sites More sharing options...
NotionCommotion Posted June 27, 2020 Author Share Posted June 27, 2020 2 hours ago, requinix said: Want a hint? It's a pretty big one. array_fill_keys + array_map with array_combine + array_merge_recursive One-liner. Is array_map fed the keys and not the arrayValues? $map = array_map(function($v) { return explode('_',$v); }, $keys); Is array_fill_keys being passed an array for the second argument? Maybe another small (or big) hint? Quote Link to comment Share on other sites More sharing options...
requinix Posted June 27, 2020 Share Posted June 27, 2020 Hint #2: I gave you the function calls in order, so array_fill_keys to get one array, array_map with a simple callback that uses array_combine, and finally array_merge_recursive with both results. Hint #3a: array_fill_keys starts off your output array with no data, array_map processes your data array, array_combine does the most logical thing it can do under those circumstances. Hint #3b: If array_merge_recursive tries to merge an array and a string, it'll add the string into the array. Quote Link to comment Share on other sites More sharing options...
Barand Posted June 27, 2020 Share Posted June 27, 2020 Not a one-liner, but still shorter foreach ($keys as $i => $k) { @list($k1, $k2) = explode('_', $k); if ($k2) $$k1[$k2] = array_column($arrayValues, $i); else $$k1 = array_column($arrayValues, $i); } Quote Link to comment Share on other sites More sharing options...
NotionCommotion Posted June 28, 2020 Author Share Posted June 28, 2020 16 hours ago, requinix said: Hint #2: I gave you the function calls in order, so array_fill_keys to get one array, array_map with a simple callback that uses array_combine, and finally array_merge_recursive with both results. Hint #3a: array_fill_keys starts off your output array with no data, array_map processes your data array, array_combine does the most logical thing it can do under those circumstances. Hint #3b: If array_merge_recursive tries to merge an array and a string, it'll add the string into the array. Are you assuming starting with the $keys and $arrayValues in my original post? $arr1 = array_fill_keys($keys, []); echo(json_encode($arr1).PHP_EOL); $arr2 = array_fill_keys($keys, $arrayValues); echo(json_encode($arr2).PHP_EOL); $values = array_map(function($values) use($keys, $arr1, $arr2) { //$arr=array_combine($arr1, $values); //Array to string conversion //$arr=array_combine($arr2, $values); //Array to string conversion $arr=array_combine($keys, $values); return $arr; }, $arrayValues); echo(json_encode($values).PHP_EOL); { "time": [], "system1_typeA": [], "system2_typeA": [], "system1_typeB": [], "system3_typeC": [], "system2_typeB": [], "system1_typeC": [] } { "time": [["2020-06-28 08:46:34", 1.71, 6.29, 6.32, 5.55, 1.25, 8.81], ["2020-06-28 08:47:45", 1.88, 8.57, 8.62, 9.98, 8.33, 8.89], ["2020-06-28 08:48:10", 5.75, 4.36, 3.54, 7.93, 8.13, 1.43], ["2020-06-28 08:49:15", 7.14, 9.54, 5.39, 4.58, 5.77, 4.72], ["2020-06-28 08:50:00", 9.42, 7.44, 1.47, 1.87, 1.23, 4.79]], "system1_typeA": [["2020-06-28 08:46:34", 1.71, 6.29, 6.32, 5.55, 1.25, 8.81], ["2020-06-28 08:47:45", 1.88, 8.57, 8.62, 9.98, 8.33, 8.89], ["2020-06-28 08:48:10", 5.75, 4.36, 3.54, 7.93, 8.13, 1.43], ["2020-06-28 08:49:15", 7.14, 9.54, 5.39, 4.58, 5.77, 4.72], ["2020-06-28 08:50:00", 9.42, 7.44, 1.47, 1.87, 1.23, 4.79]], "system2_typeA": [["2020-06-28 08:46:34", 1.71, 6.29, 6.32, 5.55, 1.25, 8.81], ["2020-06-28 08:47:45", 1.88, 8.57, 8.62, 9.98, 8.33, 8.89], ["2020-06-28 08:48:10", 5.75, 4.36, 3.54, 7.93, 8.13, 1.43], ["2020-06-28 08:49:15", 7.14, 9.54, 5.39, 4.58, 5.77, 4.72], ["2020-06-28 08:50:00", 9.42, 7.44, 1.47, 1.87, 1.23, 4.79]], "system1_typeB": [["2020-06-28 08:46:34", 1.71, 6.29, 6.32, 5.55, 1.25, 8.81], ["2020-06-28 08:47:45", 1.88, 8.57, 8.62, 9.98, 8.33, 8.89], ["2020-06-28 08:48:10", 5.75, 4.36, 3.54, 7.93, 8.13, 1.43], ["2020-06-28 08:49:15", 7.14, 9.54, 5.39, 4.58, 5.77, 4.72], ["2020-06-28 08:50:00", 9.42, 7.44, 1.47, 1.87, 1.23, 4.79]], "system3_typeC": [["2020-06-28 08:46:34", 1.71, 6.29, 6.32, 5.55, 1.25, 8.81], ["2020-06-28 08:47:45", 1.88, 8.57, 8.62, 9.98, 8.33, 8.89], ["2020-06-28 08:48:10", 5.75, 4.36, 3.54, 7.93, 8.13, 1.43], ["2020-06-28 08:49:15", 7.14, 9.54, 5.39, 4.58, 5.77, 4.72], ["2020-06-28 08:50:00", 9.42, 7.44, 1.47, 1.87, 1.23, 4.79]], "system2_typeB": [["2020-06-28 08:46:34", 1.71, 6.29, 6.32, 5.55, 1.25, 8.81], ["2020-06-28 08:47:45", 1.88, 8.57, 8.62, 9.98, 8.33, 8.89], ["2020-06-28 08:48:10", 5.75, 4.36, 3.54, 7.93, 8.13, 1.43], ["2020-06-28 08:49:15", 7.14, 9.54, 5.39, 4.58, 5.77, 4.72], ["2020-06-28 08:50:00", 9.42, 7.44, 1.47, 1.87, 1.23, 4.79]], "system1_typeC": [["2020-06-28 08:46:34", 1.71, 6.29, 6.32, 5.55, 1.25, 8.81], ["2020-06-28 08:47:45", 1.88, 8.57, 8.62, 9.98, 8.33, 8.89], ["2020-06-28 08:48:10", 5.75, 4.36, 3.54, 7.93, 8.13, 1.43], ["2020-06-28 08:49:15", 7.14, 9.54, 5.39, 4.58, 5.77, 4.72], ["2020-06-28 08:50:00", 9.42, 7.44, 1.47, 1.87, 1.23, 4.79]] } [{ "time": "2020-06-28 08:46:34", "system1_typeA": 1.71, "system2_typeA": 6.29, "system1_typeB": 6.32, "system3_typeC": 5.55, "system2_typeB": 1.25, "system1_typeC": 8.81 }, { "time": "2020-06-28 08:47:45", "system1_typeA": 1.88, "system2_typeA": 8.57, "system1_typeB": 8.62, "system3_typeC": 9.98, "system2_typeB": 8.33, "system1_typeC": 8.89 }, { "time": "2020-06-28 08:48:10", "system1_typeA": 5.75, "system2_typeA": 4.36, "system1_typeB": 3.54, "system3_typeC": 7.93, "system2_typeB": 8.13, "system1_typeC": 1.43 }, { "time": "2020-06-28 08:49:15", "system1_typeA": 7.14, "system2_typeA": 9.54, "system1_typeB": 5.39, "system3_typeC": 4.58, "system2_typeB": 5.77, "system1_typeC": 4.72 }, { "time": "2020-06-28 08:50:00", "system1_typeA": 9.42, "system2_typeA": 7.44, "system1_typeB": 1.47, "system3_typeC": 1.87, "system2_typeB": 1.23, "system1_typeC": 4.79 } ] Quote Link to comment Share on other sites More sharing options...
requinix Posted June 28, 2020 Share Posted June 28, 2020 Hmm. Apparently I misread the desired output and totally didn't see the whole "split by underscore" bit. That adds a little more difficulty than I had accounted for. The one-liner was array_merge_recursive( array_fill_keys($keys, []), // initialize to key => [] ...array_map( // flatten outer values array $values => array_combine($keys, $values), // inner values arrays get keyed $arrayValues ) ) Dealing with the keys too will be getting more complicated than I would like to see in a single statement. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.