I am new to PHP and trying to loop and concatenate csv column values
My input is
and expected output is
can somebody help me how to loop the column values to get the expected output and thanks in advance.
Basically, you need to read the CSV file line-by-line, store parsed data in array, and then do some nested loops.
This code will do the job for your example (only works for 3 columns):
<?php
$rows = [];
$file = fopen("your-file.csv", "r"); // open your file
while (!feof($file)) { // read file till the end
$row = fgetcsv($file); // get current row as an array of elements
if (!empty($row)) { // check that it's not the empty row
array_push($rows, $row); // store row in array
}
}
fclose($file);
for ($r1 = 0; $r1 < count($rows); $r1++) {
for ($r2 = 0; $r2 < count($rows); $r2++) {
for ($r3 = 0; $r3 < count($rows); $r3++) {
echo $rows[$r1][0] . '_' . $rows[$r2][1] . '_' . $rows[$r3][2] . PHP_EOL;
}
}
}
It's pretty dirty solution, I hope that you can make it cleaner, using recursion, instead of nested loops in case if you need to parse unknown columns count.
If you have another fixed number of columns, just add more nested loops (for $r4, $r5, and so on).
More info about how to read CSV file in PHP on w3schools.com
Documentation about join() function, which is alias of implode() function on php.net
Related
I am trying to save the rows (results) from an SQL query to a csv file.
I am using array push in order to put the results in a list. Later I put the data from this list to my csv file.
My code :
while ($row = $query->fetch_assoc())
{
echo sprintf( $row['campaign']);
array_push($list, $row['campaign']);
}
The results are there because sprintf works. The problem is with the syntax of array_push. I even tried :
array_push($list, array(''.$row['campaign']);
I am getting an error:
fputcsv() expects parameter 2 to be array
The full code is here :
$list = array
(
array('old_campaign_name', 'new_campaign_name')
);
// table 1
$sql = ('select distinct(campaign) as campaign from '.$table1.'');
// Run the query
$query = $Db->query($sql);
// Check for SQL errors
if ($Db->error)
{
return ($Db->error);
}
// Put data in the list
while ($row = $query->fetch_assoc())
{
echo sprintf( $row['campaign']);
array_push($list,$row['campaign'],'');
}
$fp = fopen($location, 'w');
foreach ($list as $fields)
{
fputcsv($fp, $fields);
}
fclose($fp);
As the error says, fputcsv expects each row that you put to be an array, so it can write it out with commas separating the elements. $list should be a 2-dimensional array, so you need to push an array onto it when you're building it.
while ($row = $query->fetch_assoc() {
$list[] = array($row['campaign']);
}
BTW, $list[] = x is equivalent to array_push($list, x).
When you initially create the $list array, it is an array containing one array. But when you add more values to it from your query results, you are pushing strings onto the end of it, not arrays. In effect, you will be making something like
$list = array (
array('old_campaign_name', 'new_campaign_name'),
'first campaign',
'second campaign',
'etc.',
...
);
Because of this, when you loop over $list, the first value should work with fputcsv, because it is an array, but any subsequent values will be strings instead of arrays and will cause the error you are seeing.
You should be able to fill the $list like this:
while ($row = $query->fetch_assoc()) {
$list[] = $row;
}
$list[] = $row will not overwrite the values previously in $list. From the PHP documentation for array_push:
Note: If you use array_push() to add one element to the array it's better to use $array[] = because in that way there is no overhead of calling a function.
It works like this :
while ($row = $query->fetch_assoc())
{
// array_push($list,$row['campaign'],'');
array_push($list,array($row['campaign'], ''));
}
I am using a While loop to go through the result of a sql Query. Inside of the While loop I am using a for loop to do a "wildcard search" in an array. Right now I am getting way to many results. The goal is to compare the rows in the $social_result from the SQL query with the content of the array $email_rank_results and add 1 to the $social_cnt variable if found. I would really appreciate if someone could give me some advise on how to change the code to achieve this.
The $email_rank_results array contains values like 'google.com','facebook.com','linkedin.com','twitter.com'
The $social_result contains values like 'pages.facebook.com', 'nb-linkedin.com', 'plus.google.com'
Here is my code:
$socialSQL= sprintf("SELECT name FROM class_social");
$social_result = mysql_query($socialSQL) or die ("Error in query: $socialSQL " . mysql_error());
while($row=mysql_fetch_row($social_result)) {
$check = $row[0];
$max = count($email_rank_results);
for($x = 0; $x < $max; $x++)
{
if (stripos($email_rank_results[1],$check) !== false)
{
$social_cnt = $social_cnt+1;
}
}
}
you mixed haystack with needle
in foreach loop you compare only first element of array $email_rank_results
replace:
stripos($email_rank_results[1], $check)
with
stripos($check, $email_rank_results[$x]))
or simple use foreach loop
foreach($email_rank_results as $email_rank_result)
{
if (stripos($check, $email_rank_result) !== false)
{
$social_cnt = $social_cnt+1;
}
}
in above i assume that $email_rank_results is flat array, ie array('google.com', 'facebook.com');
This question already has answers here:
Can I mix MySQL APIs in PHP?
(4 answers)
Closed 1 year ago.
I am getting the error "Warning: mysql_field_name() expects parameter 1 to be resource, object given in... on line 28"
I am fairly new to PHP, but what I am trying to accomplish is read a HTML file and replace a custom tag with the value of the record. The tag structure is |+FIELD-NAME-Record#+| For example if my sql returns two records for the "Name" field it will look for the following two tags |+Name1+| and |+Name2+| in the HTML file and replace it with the two returned values. Say Adam and Jim.
Below is the code that I have so far.
$c = '|+Name1+|<br>|+Name2+|';
echo(ReplaceHTMLVariables(mysqli_query($con,"SELECT * FROM nc_names"),$c));
function ReplaceHTMLVariables($results, $content){
while($row = mysqli_fetch_array($results)){
//Define a variable to count what record we are on
$rNum = 1;
//Loop through all fields in the record
$field = count( $row );
for ( $i = 0; $i < $field; $i++ ) {
//Use the field name and record number to create variables to look for then replace with the current record value
$content = str_replace("|+".mysql_field_name( $results, $i ).$rNum."+|",$row[$i],$content);
}
//move to next record
$rNum++;
}
return $content;
}
Line 28 references this line
$content = str_replace("|+".mysql_field_name( $results, $i
).$rNum."+|",$row[$i],$content);
You're mixing MySQL with MySQLi, and you don't really need to do all that if you pull mysqli_fetch_assoc() instead:
function ReplaceHTMLVariables($results, $content)
{
//Define a variable to count what record we are on
$rNum = 1;
/*** Using Mysqli::fetch_assoc() ***/
while( $row = mysqli_fetch_assoc( $results ) )
{
//Loop through all fields in the record
/*** Variable $value passed by reference for performance ***/
foreach( $row as $fieldName => &$value ) {
$content = str_replace("|+".$fieldName.$rNum."+|",$value,$content);
}
++$rNum; /*** Faster than $rNum++ **/
}
return $content;
}
mysqli_fetch_assoc() Pulls the data as an associative array, with the field name as the index key.
#Barmar comment is correct, you can't mix mysql_ and mysqli_ functions, which is why you are getting the error stated
I have also made some other changes to your code to simplify it. See inline comments for explanations
$c = '|+Name1+|<br>|+Name2+|';
// database query on separate line, not in function call, so we can catch any errors
$res = mysqli_query($con,"SELECT * FROM nc_names") or die(mysqli_error());
echo(ReplaceHTMLVariables($res,$c));
function ReplaceHTMLVariables($results, $content){
//Define a variable to count what record we are on
$rNum = 1;
// use fetch_assoc instead of fetch_array
// fetch_assoc will give you an array of column_name => value pairs
while($row = mysqli_fetch_assoc($results)){
// MOVED this outside the loop or you will reset to 1 it for each loop through
//Define a variable to count what record we are on
//$rNum = 1;
// extract column names from associative array
$field_names = array_keys($row);
//Loop through all fields in the record
// use foreach loop instead of for loop (this is just my preference, not essential) // $field = count( $row );
//for ( $i = 0; $i < $field; $i++ ) {
foreach ($field_names as $field_name) {
// Use the field name and record number to create variables to look for then replace with the current record value
// build placeholder on separate line, makes code easier to read
$placeholder = "|+{$field_name}{$rNum}+|";
$content = str_replace($placeholder, $row[$field_name], $content);
}
// move to next record
$rNum++;
}
return $content;
}
I'm trying to sort data alphabetically by the COMPANY NAME from a flat file. I was thinking that a simple sort would handle this, but I was wrong. I now think that I need to use usort and cmp and then create another temp array. How can I accomplish this?
This is my current code.
$data_file = fopen($data_file_url, "r");
fgets($data_file); // IGNORE FIRST LINE IN FLATFILE - column names
while (!feof($data_file) ) {
$data_lines = fgets($data_file);
$data_ele = explode('|', $data_lines);
$company_name = $data_ele[0];
$section = $data_ele[1];
$category = $data_ele[2];
$service = $data_ele[3];
$service = substr_replace($service,"",-1); // trim last char
}
You should first store all elements in a big array and afterwards sort it using a callback:
$data_file = fopen($data_file_url, "r");
fgets($data_file); // IGNORE FIRST LINE IN FLATFILE - column names
$companies = array();
while (!feof($data_file) ) {
$data_lines = fgets($data_file);
$data_ele = explode('|', $data_lines);
$row = array();
$row['company_name'] = $data_ele[0];
$row['section'] = $data_ele[1];
$row['category'] = $data_ele[2];
$row['service'] = $data_ele[3];
$row['service'] = substr_replace($row['service'],"",-1); // trim last char
$companies[] = $row;
}
usort($companies, function ($a, $b) {
return strcmp($a['company_name'], $b['company_name']);
});
Please note: I'm using an anonymous function, introduced in PHP 5.3.0.
I would imporove upon Beats answer only by using the company name as a key in the array.
If you have multiple entries per company have a sub array.
By using the key as array it is already indexed when inserted.
I believe its faster.
You could also use fgetcsv here, which is also probably a little faster.
I have a 260k line csv file that has two columns. I have read in the csv file using fgetcsv and have a while loop which reads every line in the file. In the loop I am trying to add the values from the second column to an array.
When I have the line in to add to the array, my PHP freezes and doesn't finish. I have done debugging and the values are getting added to the array so I know that the adding to array and while loop work but I do not know why it freezes.
If I remove the line the while loop completes going through the 260k lines and then processes the rest of the file.
Here is my code:
$amountRecords = 0;
$totalValue = 0;
$valueArray = array();
// reads in csv file
$handle = fopen('Task1-DataForMeanMedianMode.csv', 'r');
// to skip the header names/values
fgetcsv($handle);
// creates array containing variables from csv file
while(($row = fgetcsv($handle, "\r")) != FALSE)
{
/*
echo "ROW CONTAINS: ";
var_dump($row[1]);
echo "<br />";
*/
$valueArray[] = $row[1];
/*
echo "VALUEARRAY NOW CONTAINS: ";
var_dump($valueArray);
echo "<br />";
*/
$totalValue = $totalValue + $row[1];
$amountRecords++;
}
And sample of csv file:
ID,Value
1,243.00
2,243.00
3,243.00
4,243.00
5,123.11
6,243.00
7,180.00
8,55.00
9,243.00
10,55.00
With an out-of-memory error, there are two general approaches. As usual with these choices, you can pick easy-but-wrong and hard-but-right. The easy-but-wrong solution is to increase your memory limit to an appropriate level:
ini_set('memory_limit', '64M');
the better (although harder) solution is to re-engineer your algorithm to not need as much memory. This is clearly the more sustainable and robust approach. To do this properly, you will need to evaluate what you need to do with the array you are building. For instance, I have written similar scripts which were importing the rows to a database. Instead of building a huge array and then inserting, I did it in batches, where I built an array of 50-100 rows, then inserted those and cleared the array (freeing the memory for re-use).
Pseudo-code:
for(each row in file) {
$rows_cache[] = $row[1];
if(count($rows_cache) >= 50) {
insert_these($rows_cache);
$rows_cache = array();
}
}
Your first row is string, maybe try adding
while(($row = fgetcsv($handle, "\r")) != FALSE)
{
if(is_numeric($row[1]))
{
$valueArray[] = $row[1];
$totalValue = $totalValue + $row[1];
$amountRecords++;
}
}
Why not drop the line:
$totalValue = $totalValue + $row[1];
from inside your loop, and instead use:
$totalValue = array_sum($valueArray);
after completing your loop
Not really the problem, but
while(($row = fgetcsv($handle, "\r")) != FALSE)
can be rewritten as
while($row = fgetcsv(...))
instead. There's no need for the explicit false check - if fgetcsv returns false, the while loop would terminate anyways. Plus this version is more legible, and not as risky. If you forget the () around the fget portion, you'll be doing the equivalent of $row = (fgetcsv() != false) and simply getting a boolean value.