Search code examples
phpcsvmultidimensional-arrayassociative-arraytranspose

Convert associative array of indexed arrays into multi-line csv text


I have a multidimensional array in which the first level keys needs to be the first line of data in .csv string.

The rows of indexed elements need to be transpose and converted into subsequent lines of csv text.

The output will be identical to a .csv file's contents, but I don't want a file to be created, just as a .csv string.

Sample data:

$data = [
     'dates' => ['2010-01-02', '2011-02-03', '2011-02-04'],
     'type1' => ['data1', 'data2', 'data3'],
     'type2' => ['data4', 'data5', 'data6']
];

Desired output string:

dates,type1,type2
2010-01-02,data1,data4
2011-02-03,data2,data5
2011-02-04,data3,data6

Solution

  • This is much more verbose than you'll likely ever need, but it allows you to have an array of n elements. zip is based off of the Python function of the same name. I did not write it.

    $data = ($data);
    $r = (call_user_func_array('zip', $data));
    
    $fin = "";
    $fin .= implode(',',array_keys($data)).PHP_EOL;
    foreach($r as $arr)
    {
        $fin .= implode(',',$arr).PHP_EOL;
    }
    
    // $fin now holds all the data. Do something with it and you're finished!
    
    function zip() {
        $args = func_get_args();
        $zipped = array();
        $n = count($args);
        for ($i=0; $i<$n; ++$i) {
            reset($args[$i]);
        }
        while ($n) {
            $tmp = array();
            for ($i=0; $i<$n; ++$i) {
                if (key($args[$i]) === null) {
                    break 2;
                }
                $tmp[] = current($args[$i]);
                next($args[$i]);
            }
            $zipped[] = $tmp;
        }
        return $zipped;
    }
    

    (check out the conversation in the comments. It's really relevant.)