0

I am uploading a CSV file/report with 10 columns but at the end of the CSV file there are a few lines that just give details about the report like

Generated By: XXX

Company Name

Report Run @ 2019-03-14

When I load the array, the keys are just numeric (from 0-9) but I wanted to make it be an associative array based on the column headers. Unfortunately this will not work for the last few lines since the array dimensions are different (1 vs 10)

Here is my code:

$csv = array_map('str_getcsv', file($_FILES['file']['tmp_name']));
array_walk($csv, function(&$a) use ($csv) {
    if(count($csv[0]) != count($a)) {
        $a = null; // Remove the array
    } else {
        $a = array_combine($csv[0], $a); 
    }
});
array_shift($csv); # remove column header

When I do $a = null; it sort of 'deletes it' by replacing it with NULL. When I iterate through the arrays I do if(is_null($row)) continue; to ignore the NULL element. Is there a way to actually delete the array?

Community
  • 1
  • 1
Bijan
  • 7,737
  • 18
  • 89
  • 149
  • Possible duplicate of https://stackoverflow.com/questions/26377761/deleting-rows-in-callback-function-in-array-walk? – Daniel G Mar 14 '19 at 19:37
  • You could use [`array_filter()`](http://php.net/manual/en/function.array-filter.php) with no callback to remove null elements. – Nigel Ren Mar 14 '19 at 19:38
  • Can you provide a sample CSV with 5 real lines of data and the desired PHP array result? – MonkeyZeus Mar 14 '19 at 19:39
  • `array_filter($csv)` was not actually removing the null values – Bijan Mar 14 '19 at 19:44
  • You may find the most straightforward way is to read the file in a loop and only add lines which have the full set of fields. At the moment you are loading the file and processing the whole file twice at least. – Nigel Ren Mar 14 '19 at 19:45
  • @NigelRen that is true but I guess I could use a foreach to only parse through rows that have the 10 columns instead of modifying the array and then loading it again as a foreach – Bijan Mar 14 '19 at 19:50
  • You could use https://stackoverflow.com/questions/10181054/process-csv-into-array-with-column-headings-for-key with a simple check of `if (count($row) == $expected_count) {` before you add the row to the output array. – Nigel Ren Mar 14 '19 at 19:52
  • @NigelRen: Would it be better to `if (count($row) != $expected_count) continue;` and then finish parsing the columns? – Bijan Mar 14 '19 at 19:55

2 Answers2

2

I think it's more straightforward without array_walk. array_walk is just going to apply the function to every member of the array. Setting it to null doesn't mean it's gone, it just has a null value as you've seen. If you really want it gone, you need to unset it. Just refer to $csv by key and unset the ones you don't want.

$keys = array_shift($csv);
$expected_count = count($keys);
foreach ($csv as $index => $values) {
    if (count($values) == $expected_count) {
        $csv[$index] = array_combine($keys, $values);
    } else {
        unset($csv[$index]);
    }
}
Don't Panic
  • 41,125
  • 10
  • 61
  • 80
  • I marked this as solution because it solved my problem but I ended up doing `if (count($values) != $expected_count) continue;` since I realized I don't really need to manipulate the array if I can just skip the rows with incorrect columns and continue parsing within the `foreach` – Bijan Mar 14 '19 at 19:54
0

Array_filter($csv); afterwards will remove all null/false/0 from your array.

So it may be smarter to write a custom function to remove null only.

Mruf
  • 766
  • 7
  • 16