PHP CSV to Associative Array - php

I have a CSV file that I need to import into an associative array. The data looks like this:
"General Mills Cereal",http://sidom.com/dyn_li/60.0.75.0/Retailers/Saws/120914_20bp4_img_8934.jpg,$2.25,"9-17.12 oz., select varieties","Valid Sep 14, 2012 - Sep 20, 2012",Saws,"Grocery"
I wan to transform this data into an array where I can grab values like this:
$items[$row]['title'];
$items[$row]['imgurl'];
$items[$row]['itemprice'];
$items[$row]['itemsize'];
$items[$row]['expir'];
$items[$row]['storename'];
$items[$row]['storetype'];
Where the elements above correspond to my CSV file. How can I import this file into such an array?

I would suggest using the built-in function fgetcsv
There's a simple usage example there also.

fgetcsv() will give you a numerically indexed array.
Once you have read all records in to say $rawData, which has a structure along the lines of:
$rawData = array(0 => array(0 => "General Mills Cereal",
1 => "http://sidom.com/dyn_li/60.0.75.0/Retailers/Saws/120914_20bp4_img_8934.jpg"
2 => "$2.25",
3 => "9-17.12 oz.",
4 => "select varieties",
5 => "Valid Sep 14, 2012 - Sep 20, 2012",
6 => "Saws",
7 => "Grocery"),
...);
To convert this $rawData array to what you want, you can do something like this:
$fields = array('title', 'imgurl', 'itemprice', 'itemsize',
'expir', 'storename', 'storetype');
$data = array_map(function($cRow) uses ($fields) {
return array_combine($fields, $cRow);
}, $rawData);

See below URL
CSV to Associative Array
Try it
run over the csv file line by line, and insert to array like:
$array = array();
$handle = #fopen("file.csv", "r");
if ($handle) {
while (($line = fgetcsv($handle, 4096)) !== false) {
$array[$line[0]][$line[1]][$line[2]] = $line[3];
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}

Related

Trying to build a .csv file in php from an array

I am trying to convert the following array into a .csv file where the questions will be on the first row and the corresponding answers in the second row and at the beginning a Timestamp should be there along with the time.
I have tried in the following way:
<?php
$qna = [
[
"questionNo"=> 1,
"question"=> "I am the life of the party.",
"answer"=> 2
],
[
"questionNo"=> 2,
"question"=> "I feel little concern for others.",
"answer"=> 4
],
[
"questionNo"=> 3,
"question"=> "I am always prepared.",
"answer"=> 2
],
[
"questionNo"=> 4,
"question"=> "I get stressed out easily.",
"answer"=> 4
]
];
$csv = '/home/ankur/Desktop/iq_data.csv';
$fp = fopen( $csv , 'w' );
$questionarray = array();
$answerarray = array();
$keyarray = array();
$valuearray = array();
foreach( $qna as $key => $questions) {
$questionarray[] = $questions['question'];
$answerarray[] = $questions['answer'];
}
$keyarray[] = "Timestamp";
$valuearray[] = time();
$row = array();
array_push($row,$keyarray);
array_push($row,$valuearray);
array_push($row,$questionarray);
array_push($row,$answerarray);
for($i=0; $i < count($row); $i++) {
fputcsv($fp, $row[$i] );
}
fclose( $fp );
?>
It is creating the .csv file but the timestamp and its value is not in the same row as that of the question answer as follows:
Timestamp
1676484864
I am the life of the party. I feel little concern for others. I am always prepared. I get stressed out easily.
2 4 2 4
I want that the Timestamp column to be in the same row as that of the questions as follows:
Timestamp I find it hard to imitate the behavior of other people. My behavior is usually an expression of my true inner feelings, attitudes, and beliefs.
12/3/21 14:05 TRUE TRUE
Kindly suggest if possible where am I doing it incorrectly.
You only need two lines to be inserted in your csv file, so you only need to loop the $qna array to populate two flat arrays.
You can prepopulate the first element of the first array with the static word "Timestamp" and the first element of the second array with the current unix time.
Then you loop over the $qna array to push questions and answers into their respective arrays. I am using a body-less loop, but you can perform the pushes into the array inside of a foreach loop's body if you like.
When finished populating the two arrrays, use fputcsv() to properly write to your csv file.
$csv = '/home/ankur/Desktop/iq_data.csv';
$fp = fopen($csv, 'w');
$header = ['Timestamp'];
$answers = [time()];
foreach ($qna as ['question' => $header[], 'answer' => $answers[]);
fputcsv($fp, $header);
fputcsv($fp, $answers);
fclose($fp);

PHP convert CSV to serialized array

I have a CSV file with 2 columns, id and key. An extract is...
26,"test1
test2
test3
"
54,"test34
test52
test673
"
67,"test1
test2a
test333
"
I am trying to load this file into PHP and convert the second field (key) into a serialized array, I have this so far...
$filename = 'myfile.csv';
if (($h = fopen("{$filename}", "r")) !== FALSE) {
while (($data = fgetcsv($h, 1000, ",")) !== FALSE) {
var_dump($data[1]);
}
fclose($h);
}
I am now trying to loop through the lines in $data[1] to convert them into an array, but when I do a var_dump the new lines seems to have disapeard. Am i approaching this the correct way?
Not sure what you meant by a serialized array here but I assume you want to make your key to be in a single line like below. LET ME KNOW IF I AM WRONG. So lets try like this way-
<?php
$fp = fopen('file.csv', 'r');
$csvArray = array();
while ($row = fgetcsv($fp)) {
$csvArray[$row[0]] = preg_replace("/[\r\n]/"," ",$row[1]);
}
fclose($fp);
print_r($csvArray);
?>
Output:
Array
(
[26] => test1 test2 test3
[54] => test34 test52 test673
[67] => test1 test2a test333
)

Split a Comma Separated Value of a Field

I am trying to import a CSV for a shop, with a subset of data from an existing CSV file. I need to split one item from a column (column 3, category_id) that contains multiple comma-separated values, then combine it with one other column (Product_id) to produce multiple rows in the import CSV. See the following examples.
Original CSV
Product_id;article_id;category_id;
"1";"0001";"2,4,6"
Need it into a new CSV file
Product_id;category_id
"1";"2"
"1","4"
"1","6"
I tried just the fegetcsv function to read in the CSV and to printout the whole into an array but I have no idea what to do next.
<?php
$handle = fopen ("articles.csv","r");
while ( ($data = fgetcsv ($handle, 1000, ";")) !== FALSE ) {
$column3[] = $data[3];
}
fclose ($handle);
//edit:
print_r($column3);
?>
I get:
Array ([0] => category_id [1] => 1 [2] => 0001 [3] => 2,4,6
Quick and dirty:
$csvData = file('articles.csv');
$matches = array();
$output = "";
foreach($csvData as $csvLine) {
if(preg_match('/"(.+)";".+";"(.+)"/', $csvLine, $matches))
{
$numbers = explode(',', $matches[2]);
foreach($numbers as $number) {
$output .= "\"{$matches[1]}\";\"{$number}\"" . PHP_EOL;
}
}
}

PHP looping through huge text file is very slow, can you improve?

The data contained in the text file (actually a .dat) looks like:
LIN*1234*UP*abcde*33*0*EA
LIN*5678*UP*fghij*33*0*EA
LIN*9101*UP*klmno*33*23*EA
There are actually over 500,000 such lines in the file.
This is what I'm using now:
//retrieve file once
$file = file_get_contents('/data.dat');
$file = explode('LIN', $file);
...some code
foreach ($list as $item) { //an array containing 10 items
foreach($file as $line) { //checking if these items are on huge list
$info = explode('*', $line);
if ($line[3] == $item[0]) {
...do stuff...
break; //stop checking if found
}
}
}
The problem is it runs way too slow - about 1.5 seconds of each iteration. I separately confirmed that it is not the '...do stuff...' that is impacting speed. Rather, its the search for the correct item.
How can I speed this up? Thank you.
If each item is on its own line, instead of loading the whole thing in memory, it might be better to use fgets() instead:
$f = fopen('text.txt', 'rt');
while (!feof($f)) {
$line = rtrim(fgets($f), "\r\n");
$info = explode('*', $line);
// etc.
}
fclose($f);
PHP file streams are buffered (~8kB), so it should be decent in terms of performance.
The other piece of logic can be rewritten like this (instead of iterating the file multiple times):
if (in_array($info[3], $items)) // look up $info[3] inside the array of 10 things
Or, if $items is suitably indexed:
if (isset($items[$info[3]])) { ... }
file_get_contents loads the whole file into memory as an array & then your code acts on it. Adapting this sample code from the official PHP fgets documentation should work better:
$handle = #fopen("test.txt", "r");
if ($handle) {
while (($buffer = fgets($handle, 4096)) !== false) {
$file_data = explode('LIN', $buffer);
foreach($file_data as $line) {
$info = explode('*', $line);
$info = array_filter($info);
if (!empty($info)) {
echo '<pre>';
print_r($info);
echo '</pre>';
}
}
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}
The output of the above code using your data is:
Array
(
[1] => 1234
[2] => UP
[3] => abcde
[4] => 33
[6] => EA
)
Array
(
[1] => 5678
[2] => UP
[3] => fghij
[4] => 33
[6] => EA
)
Array
(
[1] => 9101
[2] => UP
[3] => klmno
[4] => 33
[5] => 23
[6] => EA
)
But still unclear about your missing code since the line that states:
foreach ($list as $item) { //an array containing 10 items
That seems to be another real choke point.
When you do file_get_contents, it loads the stuff into the memory so you can only imagine how resource intensive the process may be. Not to mention you have a nested loop, that's (O)n^2
You can either split the file if possible or use fopen, fgets and fclose to read them line by line.
If I was you, I’d use another language like C++ or Go if I really need the speeds.

php split array string into data

Below script is shown search string in a text file, my text file has contents like:
60, 1, 1, 188, pdgje5566
60, 1, 1, 188, pdgje5565
if(!empty($extTxId)){
$searchfor = $extTxId;
$matches = array();
$handle = #fopen($file, "r");
if ($handle)
{
while (!feof($handle))
{
$buffer = fgets($handle);
if(strpos($buffer, $searchfor) !== FALSE)
$matches[] = $buffer;
}
fclose($handle);
}
print_r($matches);
it output as
Array ( [0] => 60, 1, 1, 188, ppje5566 )
however i want to explode the data which is separate by comma(,) and store into variable, is that anyway to do it?
thanks.
i want to explode the data which is separate by comma(,)
Use explode().
If this is a CSV file (or some other delimited file), I suggest looking at fgetcsv(). It is effectively fgets() and explode(), which seems to be what you need.
Since you have spaces between each comma, you can trim each element.
// Iterate through each item int the array (you can do $matches[0] if you just want the first)
foreach ($matches as $match)
{
$output_array = array_map('trim',explode(',',$match));
print_r($output_array);
}
Output:
Array
(
[0] => 60
[1] => 1
[2] => 1
[3] => 188
[4] => pdgje5565
)
Example: http://codepad.org/aSyVX5Bj
Try like
foreach(Array[0] as $element)
{
echo $element;
}
If you know the exact structure of the input you're getting, you could do something like:
$string = '60, 1, 1, 188, pdgje5565';
// Using trim just to be sure
list($varA, $varB, $varC, $varD, $varE) = explode(', ', trim($string));
This way you would get the results as follows:
$varA = 60;
$varB = 1;
$varC = 1;
$varD = 188;
$varE = 'pdgje5565';
The main advantage here is you would get decent variables instead of array with abstract indexes, but it is only good if you're sure about you're structure being constant.

Categories