I have a very specific request. I'll try to make it easy to understand.
Let's pretend we have an Excel file that's 4 rows by 2 columns (in reality it's actually 100's of rows by 2 columns) I'm using fgetcsv()
to extract the rows, that part is done!
When I execute the while statement:
while( ($row = fgetcsv($handle, 4096,",", '"' )) !== FALSE )
{
print_r($row);
}
I get:
Array
(
[0] => blah blah blah
[1] => he he he
)
Array
(
[0] => bleh bleh bleh
[1] => ha ha ha
)
Array
(
[0] => bloh bloh bloh
[1] => ho ho ho
)
Array
(
[0] => bluh bluh bluh
[1] => hu hu hu
)
I'd like to combine every 2 arrays so that we end up with:
Array
(
[0] => blah blah blah - - - bleh bleh bleh
[1] => he he he - - - ha ha ha
)
Array
(
[0] => bloh bloh bloh - - - bluh bluh bluh
[1] => ho ho ho - - - hu hu hu
)
So, when I execute the while statement,
while( ($row = fgetcsv($handle, 4096,",", '"' )) !== FALSE )
{
echo $row[0] . $row[1];
}
I only get two outputs instead of the original 4.
If /tmp/test.csv contains the following:
"blah blah blah","ha ha ha"
"bleh bleh bleh","he he he"
"bloh bloh bloh","ho ho ho"
"bluh bluh bluh","hu hu hu"
then the following code:
$handle = fopen('/tmp/test.csv', 'r');
$tmp = array();
$even = false;
while( ($row = fgetcsv($handle, 4096,",", '"' )) !== FALSE ) {
$tmp[0][] = $row[0];
$tmp[1][] = $row[1];
if ($even) {
$tmp[0] = implode(' - - - ', $tmp[0]);
$tmp[1] = implode(' - - - ', $tmp[1]);
print_r($tmp);
$tmp = array();
}
$even = !$even;
}
produces this output:
Array
(
[0] => blah blah blah - - - bleh bleh bleh
[1] => ha ha ha - - - he he he
)
Array
(
[0] => bloh bloh bloh - - - bluh bluh bluh
[1] => ho ho ho - - - hu hu hu
)
Note: You didn't specify what you wanted to do with the last line if there was an odd number of lines in the CSV file. This code will not print the last line at all in that case. If that doesn't work for you, you'll need to add something to handle that special case.
That's some *very* clever coding, thank you. The last line can be filled in manually, I suppose. It's not ideal, but it's a relatively small thing to worry about.
Since we're on the topic, what if I want to combine 3 rows rather than every 2? Or 4, or 5 rows? Just curious, what would the code be?
Quote from: Study Force on February 17, 2018, 11:10:34 AM
That's some *very* clever coding, thank you.
You are welcome. :)
Quote
The last line can be filled in manually, I suppose. It's not ideal, but it's a relatively small thing to worry about.
Since we're on the topic, what if I want to combine 3 rows rather than every 2? Or 4, or 5 rows? Just curious, what would the code be?
This version should take care of both requests for you.
$handle = fopen('/tmp/test.csv', 'r');
// Set this to the number of rows you want to concatenate together
$concat_num = 3;
$tmp = array();
$counter = 0;
while( ($row = fgetcsv($handle, 4096,",", '"' )) !== FALSE ) {
$tmp[0][] = $row[0];
$tmp[1][] = $row[1];
if (++$counter === $concat_num) {
$tmp[0] = implode(' - - - ', $tmp[0]);
$tmp[1] = implode(' - - - ', $tmp[1]);
print_r($tmp);
$tmp = array();
$counter = 0;
}
}
// Deal with any leftovers
if (!empty($tmp)) {
$tmp[0] = implode(' - - - ', $tmp[0]);
$tmp[1] = implode(' - - - ', $tmp[1]);
print_r($tmp);
}
Using the same input CSV, this version will output the following:
Array
(
[0] => blah blah blah - - - bleh bleh bleh - - - bloh bloh bloh
[1] => ha ha ha - - - he he he - - - ho ho ho
)
Array
(
[0] => bluh bluh bluh
[1] => hu hu hu
)
What an awesome script you helped me create. It works flawlessly.
Thank you!
You're welcome. :)
I've got one more challenge for you, if you don't mind...
What if I want to number each iteration, like this?
Array
(
[0] => 1) blah blah blah - - - 2) bleh bleh bleh - - - 3) bloh bloh bloh
[1] => 1) ha ha ha - - - 2) he he he - - - 3) ho ho ho
)
You didn't specify whether the numbering should reset back to 1 in every new group or should continue climbing with each subsequent group. Either option is simple, though, so here they both are.
If you want to reset the numbering back to 1 for every new group:
$handle = fopen('/tmp/test.csv', 'r');
// Set this to the number of rows you want to concatenate together
$concat_num = 3;
$tmp = array();
$counter = 0;
while( ($row = fgetcsv($handle, 4096,",", '"' )) !== FALSE ) {
// Increment the counter
++$counter;
$tmp[0][] = $counter . ') ' . $row[0];
$tmp[1][] = $counter . ') ' . $row[1];
if ($counter === $concat_num) {
$tmp[0] = implode(' - - - ', $tmp[0]);
$tmp[1] = implode(' - - - ', $tmp[1]);
print_r($tmp);
$tmp = array();
$counter = 0;
}
}
// Deal with any leftovers
if (!empty($tmp)) {
$tmp[0] = implode(' - - - ', $tmp[0]);
$tmp[1] = implode(' - - - ', $tmp[1]);
print_r($tmp);
}
Result:
Array
(
[0] => 1) blah blah blah - - - 2) bleh bleh bleh - - - 3) bloh bloh bloh
[1] => 1) ha ha ha - - - 2) he he he - - - 3) ho ho ho
)
Array
(
[0] => 1) bluh bluh bluh
[1] => 1) hu hu hu
)
If you want the numbering in each group to carry on from where the last group left off:
$handle = fopen('/tmp/test.csv', 'r');
// Set this to the number of rows you want to concatenate together
$concat_num = 3;
$tmp = array();
$counter = 0;
$running_total = 0;
while( ($row = fgetcsv($handle, 4096,",", '"' )) !== FALSE ) {
// Increment the counters
++$counter;
++$running_total;
$tmp[0][] = $running_total . ') ' . $row[0];
$tmp[1][] = $running_total . ') ' . $row[1];
if ($counter === $concat_num) {
$tmp[0] = implode(' - - - ', $tmp[0]);
$tmp[1] = implode(' - - - ', $tmp[1]);
print_r($tmp);
$tmp = array();
$counter = 0;
}
}
// Deal with any leftovers
if (!empty($tmp)) {
$tmp[0] = implode(' - - - ', $tmp[0]);
$tmp[1] = implode(' - - - ', $tmp[1]);
print_r($tmp);
}
Result:
Array
(
[0] => 1) blah blah blah - - - 2) bleh bleh bleh - - - 3) bloh bloh bloh
[1] => 1) ha ha ha - - - 2) he he he - - - 3) ho ho ho
)
Array
(
[0] => 4) bluh bluh bluh
[1] => 4) hu hu hu
)
Thank you. One tiny issue.
How can we get the count to restart inside every new array?
Quote from: Study Force on February 20, 2018, 10:04:18 PM
How can we get the count to restart inside every new array?
Quote from: Sesquipedalian on February 20, 2018, 09:27:36 PM
If you want to reset the numbering back to 1 for every new group:
$handle = fopen('/tmp/test.csv', 'r');
// Set this to the number of rows you want to concatenate together
$concat_num = 3;
$tmp = array();
$counter = 0;
while( ($row = fgetcsv($handle, 4096,",", '"' )) !== FALSE ) {
// Increment the counter
++$counter;
$tmp[0][] = $counter . ') ' . $row[0];
$tmp[1][] = $counter . ') ' . $row[1];
if ($counter === $concat_num) {
$tmp[0] = implode(' - - - ', $tmp[0]);
$tmp[1] = implode(' - - - ', $tmp[1]);
print_r($tmp);
$tmp = array();
$counter = 0;
}
}
// Deal with any leftovers
if (!empty($tmp)) {
$tmp[0] = implode(' - - - ', $tmp[0]);
$tmp[1] = implode(' - - - ', $tmp[1]);
print_r($tmp);
}
Result:
Array
(
[0] => 1) blah blah blah - - - 2) bleh bleh bleh - - - 3) bloh bloh bloh
[1] => 1) ha ha ha - - - 2) he he he - - - 3) ho ho ho
)
Array
(
[0] => 1) bluh bluh bluh
[1] => 1) hu hu hu
)
Perfect. ^^
:)
By the way, if you need a version that can handle any arbitrary number of columns in your CSV, this would do it:
$handle = fopen('/tmp/test.csv', 'r');
// Set this to the number of rows you want to concatenate together
$concat_num = 3;
$tmp = array();
$counter = 0;
while( ($row = fgetcsv($handle, 4096,",", '"' )) !== FALSE ) {
// Increment the counter
++$counter;
foreach ($row as $column_num => $column_value)
$tmp[$column_num][] = $counter . ') ' . $column_value;
if ($counter === $concat_num) {
foreach ($tmp as $column_num => $column_value)
$tmp[$column_num] = implode(' - - - ', $column_value);
print_r($tmp);
$tmp = array();
$counter = 0;
}
}
// Deal with any leftovers
if (!empty($tmp)) {
foreach ($tmp as $column_num => $column_value)
$tmp[$column_num] = implode(' - - - ', $column_value);
print_r($tmp);
}
Using that code, if test.csv contains this:
"blah blah blah","ha ha ha","la la la","ma ma ma","xa xa xa"
"bleh bleh bleh","he he he","le le le","me me me","xe xe xe"
"blih blih blih","hi hi hi","li li li","mi mi mi","xi xi xi"
"bloh bloh bloh","ho ho ho","lo lo lo","mo mo mo","xo xo xo"
"bluh bluh bluh","hu hu hu","lu lu lu","mu mu mu","xu xu xu"
Then the output will be:
Array
(
[0] => 1) blah blah blah - - - 2) bleh bleh bleh - - - 3) blih blih blih
[1] => 1) ha ha ha - - - 2) he he he - - - 3) hi hi hi
[2] => 1) la la la - - - 2) le le le - - - 3) li li li
[3] => 1) ma ma ma - - - 2) me me me - - - 3) mi mi mi
[4] => 1) xa xa xa - - - 2) xe xe xe - - - 3) xi xi xi
)
Array
(
[0] => 1) bloh bloh bloh - - - 2) bluh bluh bluh
[1] => 1) ho ho ho - - - 2) hu hu hu
[2] => 1) lo lo lo - - - 2) lu lu lu
[3] => 1) mo mo mo - - - 2) mu mu mu
[4] => 1) xo xo xo - - - 2) xu xu xu
)
I recommend using this final version in your script so that if you need to reuse this code at a later date on a different data set, you won't need to change anything.
Actually, I have another request that might challenge you.
What if I want a random $concat_num each time between 1 and 10? For instance, it changes from 2, then 7, then 9, then 10. I'm currently using the code in this post:
https://www.simplemachines.org/community/index.php?topic=558912.msg3962717#msg3962717
Good Lord, did you read my mind with that last post?
Quote from: Study Force on February 22, 2018, 12:09:49 PM
What if I want a random $concat_num each time between 1 and 10?
Replace the 3 with
mt_rand(1, 10).
That didn't do it.
Since we've placed $concat_num outside the while statement, it randomizes it at the start, not per array printed. So let's say it decides 4, all arrays are , but I don't want that.
Oh, I see. Then just change if ($counter === $concat_num) to if ($counter === mt_rand(1, 10)). If you do this, you can delete the $concat_num = 3; line, since $concat_num will no longer be doing anything.
Quote from: Sesquipedalian on February 23, 2018, 12:30:06 AM
Oh, I see. Then just change if ($counter === $concat_num) to if ($counter === mt_rand(1, 10)). If you do this, you can delete the $concat_num = 3; line, since $concat_num will no longer be doing anything.
That did it.
ty
I'm getting a strange error that I can't figure why it's happening. After a few arrays, it quits and gives me:
PHP Notice: Undefined offset: 1
For the line:
$tmp[1][] = $counter . ') ' . $row[1];
This only happened after I added:
if ($counter === $concat_num) {
Quote from: Study Force on February 23, 2018, 04:01:41 PM
if ($counter === $concat_num) {
Meant to write: $counter === mt_rand(1, 10)
When I changed it to $counter >= mt_rand(1, 10), it works.
Glad you got it sorted out. :)