CSV to Associative Array
Solution 1
run over the csv file line by line, and insert to array like:
$array = $fields = array(); $i = 0;
$handle = @fopen("file.csv", "r");
if ($handle) {
while (($row = fgetcsv($handle, 4096)) !== false) {
if (empty($fields)) {
$fields = $row;
continue;
}
foreach ($row as $k=>$value) {
$array[$i][$fields[$k]] = $value;
}
$i++;
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}
Solution 2
Too many long solutions. I've always found this to be the simplest:
<?php
/* Map Rows and Loop Through Them */
$rows = array_map('str_getcsv', file('file.csv'));
$header = array_shift($rows);
$csv = array();
foreach($rows as $row) {
$csv[] = array_combine($header, $row);
}
?>
Solution 3
To create an associative list array use something like:
$keys = fgetcsv($f);
while (!feof($f)) {
$array[] = array_combine($keys, fgetcsv($f));
}
And to traverse and filter by specific attributes write a function like:
function find($find) {
foreach ($array as $row) {
if (array_intersect_assoc($row, $find) == $find) {
$result[] = $row;
}
}
}
Where you would invoke it with $find = array(Brand=>Honda, Model=>Civic, Part=>135)
to filter out the searched models. The other positional array structure seems not very workable, unless you only want to access the "Test" attribute.
Solution 4
Try this simple algorithm:
$assocData = array();
if( ($handle = fopen( $importedCSVFile, "r")) !== FALSE) {
$rowCounter = 0;
while (($rowData = fgetcsv($handle, 0, ",")) !== FALSE) {
if( 0 === $rowCounter) {
$headerRecord = $rowData;
} else {
foreach( $rowData as $key => $value) {
$assocData[ $rowCounter - 1][ $headerRecord[ $key] ] = $value;
}
}
$rowCounter++;
}
fclose($handle);
}
var_dump( $assocData);
Solution 5
Using fgetcsv()
seems the most direct and sensible tool for the job.
csv.csv contents:
Brand,Model,Part,Test
Honda,Civic,123,244
Honda,Civic,135,434
Toyota,Supra,511,664
Code:
$assoc_array = [];
if (($handle = fopen("csv.csv", "r")) !== false) { // open for reading
if (($data = fgetcsv($handle, 1000, ",")) !== false) { // extract header data
$keys = $data; // save as keys
}
while (($data = fgetcsv($handle, 1000, ",")) !== false) { // loop remaining rows of data
$assoc_array[] = array_combine($keys, $data); // push associative subarrays
}
fclose($handle); // close when done
}
echo "<pre>";
var_export($assoc_array); // print to screen
echo "</pre>";
Output:
array (
0 =>
array (
'Brand' => 'Honda',
'Model' => 'Civic',
'Part' => '123',
'Test' => '244',
),
1 =>
array (
'Brand' => 'Honda',
'Model' => 'Civic',
'Part' => '135',
'Test' => '434',
),
2 =>
array (
'Brand' => 'Toyota',
'Model' => 'Supra',
'Part' => '511',
'Test' => '664',
),
)
ParoX
Updated on July 17, 2022Comments
-
ParoX almost 2 years
I've seen numerous examples on how to take a CSV file and then create an associative array with the headers as the keys.
For example:
Brand,Model,Part,Test Honda,Civic,123,244 Honda,Civic,135,434 Toyota,Supra,511,664
Where it would create an Array such as
Array[$num][$key]
where$key
would be Brand, Model, Part, Test.So If I wanted to access the test value "434" I would have to loop every index in the array and then ignore any Brands that were not honda, and any models that were not Civic
What I need to do is access the value most directly, instead of running through a for loop going through each $num index. I want to be able to access the value test "434" with:
Array['Honda']['Civic']['135']
or control a for statement with looping through every model Honda has... something like
foreach $model in Array['Honda']
At the very least I need to be able to go through every model given a known Brand and access all the relative info for each.
Edit:
Just to confirm I was setting this up an example. My actually data has headers like:
brand model part price shipping description footnote
Of which I need to access all the information tied to the part (price, shipping,desc, footnote)
-
Craig Hooghiem almost 11 yearsIf you were to change $array[$i][$k] = $value; to $array[$i][$fields[$k]] = $value; you would get the header as the key.
-
DWils about 10 yearsI was just about to say the same as @CraigHooghiem before I saw his comment. With
$fields[$k]
, the above answer works as expected. -
Alex over 6 yearsmarvelous code, it works great with comma separated csv. But what if it is a semicolon separated csv? I don't find the way to do the same with a semicolon separated csv.
-
Daerik over 6 years@Alex, besides arguing semantics on the acronym CSV being
Comma Separated Values
, you are able to set the delimiter of the str_getcsv function. I hope this helps! -
marcovtwout over 6 yearsIf you want to pass a parameter (like the delimiter) to str_getcsv, use this:
$rows = array_map(function($row) { return str_getcsv($row, ';'); }, file('file.csv'));
-
Daerik over 6 years@marcovtwout, keep in mind that you can pass additional arguments as the third parameter of array_map().
-
dsharhon almost 6 yearsFor CSV in a string:
$rows = array_map('str_getcsv', preg_split('/\r\n|\r|\n/', $string));
-
AngryUbuntuNerd over 5 yearsthis solution is potentially very memory hungry, as it creates an array containing the whole of the CSV file, instead of reading single lines into memory
-
jerrygarciuh about 5 yearsIf whitespace around header row values is a concern you can clean with
$fields = array_map('trim', $row);
-
Brian Stinar over 4 yearsI like this, but the lack of error handling at all makes this simpler-appearing than I felt comfortable with. I added additional checking to make sure the file opened correctly. I still think it's simpler than the other solutions here, so thanks!
-
Gsinti over 4 yearsWhy use a foreach when
array_map
works and keeps things consistent?$csv = array_map(function($row) use ($header) { return array_combine($header, $row); }, $rows);
-
Dan about 4 yearsWhy doe the first field's header have double quotes around double quotes? "LastName" in CSV becomes ""LastName"" as a header
-
mickmackusa over 3 yearsThis answer is missing its educational explanation.
-
wivku over 2 yearsThe foreach can be simplified these days:
$csv = array_map(fn($e) => array_combine($header, $e), $rows);
-
Richard over 2 yearsTip: if you use a zero (0) instead of 1000 here:
fgetcsv($handle, 0, ",")
, then there is no character limit per line. Good for if you aren't sure just how many characters might be per line. -
user2280032 about 2 yearsI have found the foreach to run one more time after all data is parsed causing the last entry to simply be false, this causes issues when then iterating and expecting keys to be present. A for loop with count(rows) would probably be better here.