I am seeking constructive feedback/advice that will give me the best
chance of a successful RFC when I eventually submit it.

Introduction:

PHP developers have had an appetite for transposing data for many
years; this is indicated by the nearly 100 Stack Overflow pages on
this narrow topic.
There are many non-native techniques being used to transpose
multidimensional data sets, but each of them are some combination of
verbose, convoluted, restrictive, and/or even flawed.
Transposing comes in handy when re-orientating data for server-side
storage or graphical/tabular display.
Ideally, PHP should have a native transposing function to put
developers out of their misery -- much like array_key_last() did.


Proposal:

Let's create an intuitive transposing function for data sets with a
minimum depth of 2 levels.
The function should also return the input parameter without complaint
when the input parameter is an empty array/object.
The previous two points are purposely stated so that this function can
accommodate fetch-all result sets from database queries (e.g.
array_transpose($stmt->fetchAll(PDO::FETCH_ASSOC));).
As a matter of flexibility, there should be no requirement that the
lone parameter be a matrix or dense data structure.
It should also preserve keys to give it a clear advantage over
pre-existing functional techniques.
The function must never receive or return a non-empty one-dimensional array.
A potential consideration is to preserve data types while transposing
-- see implementation #2 and its demo link with test data.


Background:

Here are some of the popular techniques that this new function would replace:


    array_unshift($array, null);
    return call_user_func_array('array_map', $array);
    // outdated, unintuitive, unreliable, requires non-numeric
first-level keys, destroys associative keys
    // [['single' => 'row']] becomes ['single' => 'row'] but should be
['single' => ['row']]

    return array_map(null, ...$array);
    // unintuitive, unreliable, requires non-numeric first-level keys,
destroys associative keys
    // [['single' => 'row']] becomes ['single' => 'row'] but should be
['single' => ['row']]

    $out = [];
    foreach ($arr as $key => $subarr) {
        foreach ($subarr as $subkey => $subvalue) {
            $out[$subkey][$key] = $subvalue;
        }
    }
    return $out;
    // reliable, but verbose and not functional-style

    $keys = array_keys($array);
    return array_map(function($array) use ($keys) {
        return array_combine($keys, $array);
    }, array_map(null, ...array_values($array)));
    // convoluted, unintuitive, requires input to be a matrix
    // [['single' => 'row']] generates Warning: array_combine()
expects parameter 2 to be array, string given"


Considerations:

Should the function unconditionally return an array of arrays?
Should it preserve the initial data types of the first and second level?
Should data type preservation be excluded to increase the chances of
its implementation?


Rough implementations of behavior:

    1. Unconditionally cast output as array of arrays.

        function array_transpose(array|object $object_or_array): array|object {
            $levelOneType = gettype($object_or_array);
            if (!in_array($levelOneType, ['array', 'object'])) {
                throw new Exception("Error: array_transpose() expects
parameter 1 to be an array or object, $levelOneType given");
            }
            $result = [];
            foreach ($object_or_array as $rowKey => $row) {
                $levelTwoType = gettype($row);
                if (!in_array($levelTwoType, ['array', 'object'])) {
                    throw new Exception("Error: array_transpose()
expects parameter 1 to contain rows of arrays or objects,
$levelTwoType given");
                }
                foreach ($row as $columnKey => $value) {
                    $result[$columnKey][$rowKey] = $value;
                }
            }
            return $result;
        }

    2. Preserve original data types of level one and level two.
https://3v4l.org/RRKlr

(If input is two dimensional, then the first occurring data type in
the second level will dictate the result's first level data type.)


        function array_transpose(array|object $object_or_array): array|object {
            $levelOneType = gettype($object_or_array);
            if (!in_array($levelOneType, ['array', 'object'])) {
                throw new Exception("Fatal error: Uncaught TypeError:
array_transpose(): Argument #1 ($object_or_array) must be of type
object|array, $levelOneType given");
            }
            foreach ($object_or_array as $rowKey => $row) {
                $levelTwoType = gettype($row);
                if (!in_array($levelTwoType, ['array', 'object'])) {
                    throw new Exception("Fatal error: Uncaught
TypeError: array_transpose(): Argument #1 ($object_or_array) must
contain rows of type object|array, $levelTwoType given");
                }
                $result ??= ($levelTwoType === 'array' ? [] : (object)[]);
                foreach ($row as $columnKey => $value) {
                    if ($levelTwoType === 'array') {
                        if ($levelOneType === 'array') {
                            $result[$columnKey][$rowKey] = $value;
                        } else {
                            $result[$columnKey]->$rowKey = $value;
                        }
                    } else {
                        if (!property_exists($result, $columnKey)) {
                            $result->$columnKey = ($levelOneType ===
'array' ? [] : (object)[]);
                        }
                        if ($levelOneType === 'array') {
                            $result->{$columnKey}[$rowKey] = $value;
                        } else {
                            $result->{$columnKey}->$rowKey = $value;
                        }
                    }
                }
            }
            return $result ?? ($levelOneType === 'array' ? [] : (object)[]);
        }


RFC Impact:

I can't see any backward incompatible concerns, but it is possible
that this new native function may impact codes where the function name
is already in use. (e.g.
https://github.com/josefernandotrindade/array_transpose/blob/master/transpose.php)
Pre-existing projects may have different rules relating to the
specific handling of data types and data structures.
No new constants.
No php.ini defaults.


Future Scope:

If only initially implemented to return an array of arrays, then
expanding the result data types in the future may be of interest.


List of Stack Overflow pages which seek to implement transposition
(approaching 100K page views in the aggregate): link list @
https://meta.stackoverflow.com/q/417663/2943403
2009 Transposing multidimensional arrays in PHP -- 50K views
2009 Joining Arrays in PHP -- 150 views
2010 Is there better way to transpose a PHP 2D array? -- 5K views
2010 Combine 3 or more arrays (php) -- 4K views
2010 Can I convert individual fields of a 'mysql_query' to arrays? -- 500 views
2011 Combine arrays in PHP 300 views
2011 PHP: Take several arrays, and make new ones based on shared
indexes? -- 100 views
2011 Insert Multiple rows using implode -- 3K views
2011 how convert the element structure of an array in php -- 100 views
2011 php reassign array contents -- 150 views
2012 PHP Grouping Array by Index -- 1K views
2012 displaying a mysql table vertically - for comparison or for print
out purposes -- 4K views
2012 Elegant way to convert associative array into an indexed one -- 3K views
2012 PHP Grouping Array by Index -- 1K views
2012 Order in loops foreach -- 350 views
2012 PHP Array, Move Elements -- 100 views
2013 Refactor (transpose) array to unique keys -- 200 views
2013 How to merge 3 arrays into one big array (same keys) -- 200 views
2013 Smarty/PHP - How to match up keys between 3 different arrays? -- 750 views
2013 PHP rotate matrix counter-clockwise -- 3K views
2013 loop to populate html table vertically -- 9K views
2013 How to merge 3 arrays into one big array (same keys) -- 200 views
2014 PHP looping array to get combined rows of items -- 50 views
2014 MYSQL / Query Builder / Eloquent - Transpose rows to columns -- 1k views
2014 Change several ARRAY into new ARRAYS -- 50 views
2014 array merge issue in php -- 50 views
2014 How to combine associative array by indexes -- 450 views
2014 PHP: Grouping array values by keys -- 150 views
2014 How to transpose two arrays to form an indexed array of
associative arrays? -- 100 views
2014 PHP - multidimensional array from arrays -- 100 views
2014 Display transposed data as html table -- 100 views
2015 I have 5 arrays each array contains 10 values, I want to invert
these arrays into 10 arrays and each array contains 5 values using
php? -- 6K views
2015 create transpose matrix using php -- 6K views
2015 Why does array_map() with null as callback create an "array of
arrays"? -- 2K views
2015 Chunk and transpose a flat array into rows with a specific number
of columns -- 50 views
2015 Merge 2 arrays into 1 multidimensional array by index -- 800 views
2015 Merging two simple arrays into a multidimensional array -- 50 views
2015 Populating HTML table with multidimensional array vertically -- 1K views
2015 Merge multidimensional array preserving keys -- 100 views
2015 Transpose csv file data -- 300 views
2016 Multi dimensional loops from 4 existing arrays -- 50 views
2016 How to use an array of arrays with array_map(...) in PHP? -- 2K views
2016 How can I combine arrays in one multidimensional array in php? -- 50 views
2016 PHP array, move keys and values to new array, but mix it up -- 50 views
2016 How to transpose array elements? -- 900 views
2016 Hierarchical Array Conversion to Flat Array -- 300 views
2016 merge and reorder 3 arrays -- 50 views
2016 Insert database rows from columns of data from associative array
of indexed arrays -- 50 views
2017 Transpose rows and columns in a 2D array -- 5K views
2017 php reformat array representation from html form array -- 50 views
2017 How to insert arrays into a main array in PHP to make it 2d
array? -- 50 views
2017 How can I combine array's items? -- 250 views
2017 Restructure multidimensional array of column data into
multidimensional array of row data -- 1K views
2017 Transpose associative array of associative arrays to create
associative array of indexed arrays -- 4K views
2017 Merging PHP array to multidimensional array from another array -- 50 views
2018 Combine items of two array and create new array using php -- 50 views
2018 How to collect 3 arrays in 1 array using PHP? -- 50 views
2018 How do I use array_map recursively in PHP? -- 1K views
2018 Laravel loop through set of input arrays -- 150 views
2018 Foreach to combine to array -- 50 views
2019 php extract associate arrays -- 50 views
2019 How to combine and transpose 2 PHP arrays -- 50 views
2019 How to merge two arrays into one without iteration -- 100 views
2019 How to create an associative array from two arrays? -- 3K views
2019 how to get each column of values as array directly, and without
using pluck laravel? -- 650 views
2019 Combine (merge) 2 arrays by keys and change keys name in the
result array -- 800 views
2019 Array_map and array_combine for more than two arrays -- 500 views
2019 Merge values from different arrays to one with the same key -- 100 views
2019 Native PHP function that pairs elements from arbitrary number of
input arrays -- 50 views
2019 Transpose multidimensional array and join values with commas -- 50 views
2019 How to create 3 arrays from 1 multidimensional array with 2
arrays inside -- 50 views
2019 How to store 3 key by index per row PHP -- 50 views
2019 How to change associative array value in php -- 400 views
2019 How to put array inside array in PHP? -- 50 views
2019 How to Loop through multi dimensional array of $_FILES array -- 200 views
2019 How to change associative array value in php -- 400 views
2019 PHP multi-dimensional array, merge duplicate keys into new arrays
-- 50 views
2020 Transpose of column to row in php -- 50 views
2020 combine and merge array in laravel -- 100 views
2021 how to import a transposed excel in Laravel using laravel-excel
-- 450 views
2021 Transpose imported Excel with Matrix table to Laravel -- 50 views
2021 Group multi array by key and value PHP -- 50 views
2021 Create a multidimensional array based on number of values -- 50 views
2022 Rotate a Collection in laravel -- 50 views
2022 Zip multiple arrays in PHP based on their identical keys and not
their indices or their positions in array -- 50 views
2022 Convert nested associative array to single array in php -- 50 views


Stack Overflow transposition pages not in PHP:

What is the fastest way to transpose a matrix in C++?
Transpose/Unzip Function (inverse of zip)?
Transposing a 2D-array in JavaScript
An efficient way to transpose a file in Bash
Java: Multi-dimensional array transposing


mickmackusa

p.s. I've been told that I'll need a sprinkling of karma if I am going
to submit an RFC, so please shout me some of that.

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to