1

I have a large (size ~ 12k) 2D array of data like below and I want to insert these data into a csv file.

$data = array
(
    'a' => array
    (
        0 => 111,
        1 => 222,
        2 => 333,
        3 => 444,
    ),
    'b' => array
    (
        0 => 555,
        1 => 666,
        2 => 777,
        3 => 888,
    ),
    'c' => array
    (
        0 => 999,
        1 => 000,
        2 => 111,
        3 => 222,
    ),
);

Here 'a', 'b', and 'c' would be the CSV header row, and corresponding array values should be inserted like below:-

a b c
111 555 999
222 666 000
333 777 111
444 888 222

I know fputcsv can be used to insert the data but it insert the array values as a row in the csv but in my case I want to insert the array values to a csv column.

Is there any simpler way to insert all the array values to the csv columns like above table?

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Arpit Jain
  • 1,599
  • 9
  • 23

3 Answers3

2

There exists an array_column function that might be of help:

$out = fopen('php://stdout', 'w');

# output the CSV header
fputcsv($out, array_keys($data));

# output the CSV records
foreach ( array_keys( $data[ array_key_first($data) ] ) as $column_key) {
     fputcsv($out, array_column($data, $column_key));
}

output:

a,b,c
111,555,999
222,666,0
333,777,111
444,888,222
Fravadona
  • 13,917
  • 1
  • 23
  • 35
1

Assuming that each sub-array contains the same count of values, you can achieve your goal with just a few lines of code:

  • use array_keys to get all the column names from your array
  • iterate each sub-array to compose the single row, assuming that each value of that row is in the same array index position
$data = array
(
    'a' => array
    (
        0 => 111,
        1 => 222,
        2 => 333,
        3 => 444,
    ),
    'b' => array
    (
        0 => 555,
        1 => 666,
        2 => 777,
        3 => 888,
    ),
    'c' => array
    (
        0 => 999,
        1 => 000,
        2 => 111,
        3 => 222,
    ),
);
    
$fp = fopen('file.csv', 'w');

// headers
fputcsv($fp, array_keys($data));

// rows contents
for($i = 0; $i<count(current($data)); $i++) {
    $row = [];
    foreach($data as $k => $v) {
        $row[] = $v[$i];
    }
    fputcsv($fp, $row);
}
    
fclose($fp);

Try it online on https://onlinephp.io/c/735bc, with this results:

a,b,c
111,555,999
222,666,0
333,777,111
444,888,222

In the official documentation you can find many other useful array functions.

user2342558
  • 5,567
  • 5
  • 33
  • 54
1

Since CSV files are fundamentally written row by row, you'll need to:

  • Determine how many rows you want to generate
  • Loop that many times, picking one item for each column

Assuming all your sub-arrays have the same number of keys, you could set up this way:

$lastRowNumber = array_key_last($data['a']);
$columns = array_keys($data);

And then your loop would look like this:

for ( $rowNumber = 0; $rowNumber <= $lastRowNumber; $rowNumber++ ) {
    $csvRow = [];
    foreach ( $columns as $columnKey ) {
        $csvRow[] = $data[$columnKey][$rowNumber];
    }
    fputcsv($outputFileHandle, $csvRow);
}

Demo echoing the data rather than writing with fputcsv: https://3v4l.org/P5rtU

Alternatively, you could loop using a list of row keys, rather than assuming they're sequentially numbered. For instance, taking the keys from the first sub-array:

$columnKeys = array_keys($data);
$rowKeys = array_keys($data[$columnKeys[0]]);

Then use foreach instead of for:

foreach ( $rowKeys as $rowKey ) {
    $csvRow = [];
    foreach ( $columnKeys as $columnKey ) {
        $csvRow[] = $data[$columnKey][$rowKey];
    }
    echo implode(',', $csvRow), PHP_EOL;
}
IMSoP
  • 89,526
  • 13
  • 117
  • 169
  • I was also thinking to kind of transform the array and then insert with `fputcsv`. I tried @user2342558 answer and it is working fine for me. Although, thanks for your response :) – Arpit Jain Apr 06 '23 at 10:42