Search code examples
phpfgetcsv

Parsing CSV to get specific columns


I have a CSV file with several headers.

I only need about 5 of these columns.

I'm trying to get these into a more manageable format (variables?) so I can then do a check on their values.

I have the following code:

    $headers    = array('NAME', 'EMAIL');
    $picked     = array();
    $theData    = array();
    $isFirstRow = true;
    if (($handle = fopen($uploadedFile, "r")) !== FALSE) {
        while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
            $numCols = count($data);
            $row     = array();

            if($isFirstRow) {
                for($c=0; $c<$numCols; $c++) {
                    if(!in_array($data[$c], $headers)) {
                       continue;
                    } else {
                        $picked[] = $c;
                        $isFirstRow = false;
                    }
                }
            } else {
                for($c=0; $c < $numCols; $c++) {
                    if(in_array($c, $picked)) {
                        $row[] = $data[$c];
                        $theData[] = $row;
                    }
                }
            }
        }
        fclose($handle);


    }
    var_dump($theData);

This outputs the following:

array (size=xxxxxx)
  0 => 
    array (size=1)
      0 => string 'John Doe' (length=8)
  1 => 
    array (size=2)
      0 => string 'John Doe' (length=8)
      1 => string '[email protected]' (length=16)
  2 => 
    array (size=1)
      0 => string 'Jane Doe' (length=8)
  3 => 
    array (size=2)
      0 => string 'Jane Doe' (length=8)
      1 => string '[email protected]' (length=16)

Obviously this isn't the expected output

I'd like something more like:

array (size=xxxx)
  0 =>
    array (size=1)
      0 => string 'John Doe' (length=8)
      1 => string '[email protected]' (length=16)
  1 =>
    array (size=2)
      0 => string 'Jane Doe' (length=8)
      1 => string '[email protected]' (length=16)

I'not sure why its adding the extra arrays.

Anyone have an idea?

Thanks

EDIT

My CSV looks like this;

NAME,EMAIL
John Doe,[email protected]
Jane Doe,[email protected]

Solution

  • Edit: New answer.

    So there's a somewhat convoluted solution that does this:

    • Takes your CSV data
    • Combine the numeric key data with ALL available headers, giving you a key => value array
    • Intersect this with your ALLOWED headers
    • Add this to the final data array
    • Removes the header row

    There we go. It's awful to read, but it seems to be fine. As all the array manipulation is C based, it should be faster than manipulating thousands of rows in PHP.

        $availableHeaders = array('NAME', 'THING', 'EMAIL');
        $headers    = array('NAME', 'EMAIL');
        $theData    = array();
    
        if (($handle = fopen($uploadedFile, "r")) !== FALSE) {
            while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
                $theData[] = array_intersect_key(array_combine(array_values($availableHeaders), array_values($data)), array_flip($headers));
            }
            fclose($handle);
        }
    
        array_shift($theData); // Remove headers