开发者

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:

开发者_如何学C$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


Something like this would probably come close to what you want (not tested, just going off the top of my head):

$fh = fopen('file.csv', 'w');

// write out the headers
fputcsv($fh, array_keys($data));

// write out the data    
for ($i = 0; $i < count($data['dates']); $i++) {
    $temp = array($data['dates'][$i], $data['type1'][$i], $data['type2'][$i]);
    fputcsv($fh, $temp);
}


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


I made a little class for doing this: https://gist.github.com/981720

You can include it and generate the csv like so:

CSV::export($field_names, $data, '', TRUE)


This is merely the same as Marc B suggested, however you wrote that you didn't wanted to create a file for this. Stream Wrappers to the rescue (not tested, just going off the top of my head):

$fh = fopen('php://memory', 'rw'); # don't create a file, write to memory instead

// write out the headers
fputcsv($fh, array_keys($data));

// write out the data    
for ($i = 0; $i < count($data['dates']); $i++) {
    $temp = array($data['dates'][$i], $data['type1'][$i], $data['type2'][$i]);
    fputcsv($fh, $temp);
}
rewind($fh);
$string = stream_get_contents($fh);
fclose($fh);


The task is to create a .csv-ready string. In other words, a comma-delimited line of header data, followed by n number of transposed column data joined as comma-delimited lines.

To transpose a multidimensional array, call array_map() and feed it an unpacked (...) indexed array then collect columns of data inside the callback (...$col) and implode.

After all data is merged into a single array of strings, implode the first level with \n or PHP_EOL.

Code: (Demo)

echo implode(
         "\n",
         array_merge(
             [implode(',', array_keys($data))],
             array_map(
                 fn(...$col) => implode(',', $col),
                 ...array_values($data)
             )
         )
     );

Output:

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

This is a reliable dynamic snippet for the desired result and at no point hard codes any key names.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜