Shy
Shy

Reputation: 536

Fatal error: Allowed memory size exhausted while looping through a 14 element long single-character-array

I have a simple string. I need to produce an output Array such that the order of every 2 consecutive characters is reversed.

Input string is 14f05000034e69 and I need the following output Array [4, 1, 0, f, 0, 5, 0, 0, 4, 3, 6, e, 9, 6].

Here is my PHP code:

$myString = "14f05000034e69";
$myStringArray = str_split($myString);

$newArray = array();
for ($index=0; $index<count($myStringArray)-1; $index+2) {
    $newArray[] = $myStringArray[$index+1];
    $newArray[] = $myStringArray[$index];
}

print_r($newArray);

And it is giving me

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 134217736 bytes) in /var/www/html/test.php on line 8

The question is why and how do I fix it?

Upvotes: 2

Views: 848

Answers (4)

Elementary
Elementary

Reputation: 1453

An answer has already been marked as the solution an many other answers too however I think this can help to know that we can achieve the inversion in the string itself and then split it.If an array is not needed we can just keep the string.This way we use less memory i think:

    $myString = "14f05000034e69";
    $length=strlen($myString);
    for ($index=-1, $length=$length%2==0?$length-1:$length-2; $index<$length-1; $index+=2) {
        $tmp=$myString[$index+1];
        $myString[$index+1]=$myString[$index+2];
        $myString[$index+2]=$tmp;
    }


print_r(str_split($myString));// return an array 
print_r($myString); //here a string

This can handle variable length of strings

Upvotes: 2

Rafael
Rafael

Reputation: 1535

In my opinion, the str_split is redundant in this operation, strings can be iterated through as of arrays, like this:

$myString = "14f05000034e69";

$newArray = array();
for ($index=0; $index<strlen($myString)-1; $index+=2) 
{
    $newArray[] = $myString[$index+1];
    $newArray[] = $myString[$index];
}

print_r($newArray);

But yeah, as said before, just missing += in the for loop.

I made a small test on regex to see if it could be done, works as a charm. But of course, I only deliver a string in this case. :)

$myString = "14f05000034e69";

$test = preg_replace('/(.)(.)/', '$2$1', $myString);

echo $test;

This is the most elegant solution I could come up with.

Code tested here: https://3v4l.org/mtdca

And for the regex: https://3v4l.org/nI4UP

Upvotes: 2

Nigel Ren
Nigel Ren

Reputation: 57131

The shortest alternative I could come up with is to use some of the array methods instead...

$myString = "14f05000034e69";

$out = str_split(implode(array_map ('strrev', str_split($myString, 2))));

print_r( $out );

This uses str_split() to split it into 2 char chunks, then uses array_map() and strrev() to reverse each item and then implode() to put them all back again.

The outer call to str_split() just splits the result back down to 1 char elements in an array for the output (miss this off if you just need the string itself)

Upvotes: 2

pr1nc3
pr1nc3

Reputation: 8348

<?php


$myString = "14f05000034e69";
$myStringArray = str_split($myString);

$i=0;
foreach($myStringArray as $row){
    if(array_key_exists($i,$myStringArray)) {
        $newArray[$i] = $myStringArray[$i + 1];
        $newArray[$i + 1] = $myStringArray[$i];
        $i = $i + 2;
    }
}

echo '<pre>';
print_r($newArray);

I found a workaround in a bit "dirty" way but i managed to do what you asked.

Basically i split the string like you did but i play with the new array positions around and push in my new array the positions that i want to that's why i used a counter for that.

The output is:

Array
(
    [0] => 4
    [1] => 1
    [2] => 0
    [3] => f
    [4] => 0
    [5] => 5
    [6] => 0
    [7] => 0
    [8] => 3
    [9] => 0
    [10] => e
    [11] => 4
    [12] => 9
    [13] => 6
)

Basically i thought that i need to loop the array by two but every time i loop i need to handle 2 array positions and then the next two.

So that led me to handle my $new_array in a way that i push at the same time data in the current position i am and in the next position, that's why the counter $i+1 is used to handle array position.

If i did not use it there and used simple $newArray[] it would put the data in my current position and overwrite it again in the second step and also i could not move my array pointer to positions 1,3,5,6 etc etc that's why i am "forcing" it to use my $i counter so i keep pointing every after position.

My $i counter is set at the end of each loop to move with step 2.

Upvotes: 2

Related Questions