News:

Bored?  Looking to kill some time?  Want to chat with other SMF users?  Join us in IRC chat or Discord

Main Menu

How to combine arrays?

Started by Biology Forums, February 16, 2018, 11:37:03 AM

Previous topic - Next topic

Biology Forums

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($handle4096,","'"' )) !== 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($handle4096,","'"' )) !== FALSE 
{
	
	

	
echo 
$row[0] . $row[1];
}


I only get two outputs instead of the original 4.

Sesquipedalian

#1
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($handle4096,","'"' )) !== 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.
I promise you nothing.

Sesqu... Sesqui... what?
Sesquipedalian, the best word in the English language.

Biology Forums

#2
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?

Sesquipedalian

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($handle4096,","'"' )) !== 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
)
I promise you nothing.

Sesqu... Sesqui... what?
Sesquipedalian, the best word in the English language.

Biology Forums

What an awesome script you helped me create. It works flawlessly.

Thank you!

Sesquipedalian

I promise you nothing.

Sesqu... Sesqui... what?
Sesquipedalian, the best word in the English language.

Biology Forums

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
)


Sesquipedalian

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($handle4096,","'"' )) !== 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($handle4096,","'"' )) !== 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
)
I promise you nothing.

Sesqu... Sesqui... what?
Sesquipedalian, the best word in the English language.

Biology Forums

Thank you. One tiny issue.

How can we get the count to restart inside every new array?

Sesquipedalian

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($handle4096,","'"' )) !== 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
)

I promise you nothing.

Sesqu... Sesqui... what?
Sesquipedalian, the best word in the English language.


Sesquipedalian

:)

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($handle4096,","'"' )) !== 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.
I promise you nothing.

Sesqu... Sesqui... what?
Sesquipedalian, the best word in the English language.

Biology Forums

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?

Sesquipedalian

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).

I promise you nothing.

Sesqu... Sesqui... what?
Sesquipedalian, the best word in the English language.

Biology Forums

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.

Sesquipedalian

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.
I promise you nothing.

Sesqu... Sesqui... what?
Sesquipedalian, the best word in the English language.

Biology Forums

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

Biology Forums

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) {

Biology Forums

#18
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.

Sesquipedalian

I promise you nothing.

Sesqu... Sesqui... what?
Sesquipedalian, the best word in the English language.

Advertisement: