Explode() 'manual' in PHP

Asked

Viewed 185 times

4

Just for the challenge and the taste of programming I’m trying to recreate the function explode() in PHP. This is what I have so far:

function explode_by_me($divideBy, $str) {

   $element = "";
   $elements = array();

   for($i=0, $strCount = strlen($str); $i<$strCount; $i++) {
      if($str[$i] == $divideBy) {
         $elements[] = $element;
         $element = "";
      }
      else {
         $element .= $str[$i];
      }
   }

   // add last item
   $elements[] = $element;

   return $elements;
}

$str = "yo, yo, yo, sexy mama, brhh";
$divideBy = ",";

$explodeNative = explode($divideBy, $str);
$explodeMe = explode_by_me($divideBy, $str);

print_r($explodeNative); //Array ( [0] => yo [1] => yo [2] => yo [3] => sexy mama [4] => brhh ) 
print_r($explodeMe);     //Array ( [0] => yo [1] => yo [2] => yo [3] => sexy mama [4] => brhh )

Everything seems to be fine, except if ours $divideBy has more than one char, ex:

$divideBy = ", ";

$explodeNative = explode($divideBy, $str);
$explodeMe = explode_by_me($divideBy, $str);

print_r($explodeNative); //Array ( [0] => yo [1] => yo [2] => yo [3] => sexy mama [4] => brhh ) 
print_r($explodeMe);     //Array ( [0] => yo, yo, yo, sexy mama, brhh )

I understand why this happens, in this case, is why we are comparing a single char ($str[$i]) to a set of chars (", "). I tried to circumvent this by changing the condition within our cycle:

if (strpos($divideBy, $str[$i]) !== False) {
   $elements[] = $element;
   $element = "";
}

But it doesn’t work either:

print_r($explodeNative); //Array ( [0] => yo [1] => yo [2] => yo [3] => sexy mama [4] => brhh ) 
print_r($explodeMe);     //Array ( [0] => yo [1] => [2] => yo [3] => [4] => yo [5] => [6] => sexy [7] => mama [8] => [9] => brhh ) 1

I also understand that this happens, as we are creating a new element in the array for each char of $divideBy.

Someone with a solution, to recreate the explode() in PHP?

  • 2

    The function explodes from PHP in Javascript to give you an idea: http://phpjs.org/functions/explode/

2 answers

2


Just as you said yourself, the problem is that you are comparing a single char, with a set of char. You can solve this as follows:

if(strpos(substr($str, $i), $divideBy) === 0)

The previous statement does the following, from the inside out:

  • Replace query a part of the string of the first parameter based on the second parameter: substr('Hello', 2) => 'llo'
  • Strpos returns the position of string of the second parameter, in string of the first parameter: strpos('Hello', 'll') => 2

Then combining these two functions, you can get the desired result, IE, go reading the current string and see if in position 0, or first character, is your divisor, if it is, skip the number of characters of the divisor size.

So, there are several ways to do this, here one that I think is clean and simple: (I commented well on the function for understanding)

function myexplode($divisor, $string){

  // Se não tiver o divisor na string retorna com array de 1 posição com a 
  // string completa.
  if(strpos($string, $divisor) === -1)
     return [$string];

  // Tamanho da string
  $len = strlen($string);

  // Array que será retornado
  $ret = array();

  // Posição da string atual no array de retorno
  $p = 0;

  // Começa a ler a string
  for ($i=0; $i < $len; $i++) { 

     // pega a string que não foi lida ainda, ou seja
     // se a posição atual é 2, e a string é "Hello world!"
     // o valor de s será "llo world!"
     $s = substr($string, $i);

     // verifica se os primeiros caracteres é igual ao divisor, ou seja
     // se o divisor é ",", verifica se o primeiro caracter da string 
     // s "llo world!" começa com ","

     if (strpos($s , $divisor) === 0){
        // Se começar pula o tamanho de caracteres do divisor
        $i = $i + (strlen($divisor)-1);
        // Nova posição no array de retorno
        $p++;
     } else {
        // Verifica se a posição existe
        if (empty($ret[$p])) 
           // Se não existir, cria com o caracter atual da string
           $ret[$p] = $string[$i];
        else
           // Se existir, concatena com o caracter atual
           $ret[$p] .= $string[$i];
     }
  }

  // retorna o array com todos os campos
  return $ret;

}

// Teste
$array = myexplode(', ', 'yo, yo, yo, sexy mama, brhh');
var_dump($array);
/*
  Retorno:
  array(5) {
    [0]=> string(2) "yo"
    [1]=> string(2) "yo"
    [2]=> string(2) "yo"
    [3]=> string(9) "sexy mama"
    [4]=> string(4) "brhh"
  }

*/
  • Very clear, Thank you, I just changed the condition to the one you showed me (if(strpos(substr($str, $i), $divideBy) === 0)), and everything seems to be okay

1

You have to use the divideBy as array to give for all cases:

function explode_by_me( $divideBy, $str ) 
{
    $element     = "";
    $elements    = array();
    $count       = 0;

    $strCount    = strlen( $str      ); 
    $divideCount = strlen( $divideBy ); 
    $j=0;

    for($i=0; $i<$strCount; $i++) 
    {       
        if ($divideBy[$j] == $str[$i] && $j<$divideCount)
        {
            $j++;
            continue;
        }
        else if ($j==$divideCount)
        {
            $elements[] = $element;
            $element    = "";
            $j          = 0; 
            $element   .= $str[$i];
        }  
        else 
        {
            $count=$i;  
            $element .= $str[$count];
        }
    }

    $elements[] = $element;

    return $elements;
}

$str = "yo, yo, yo, sexy mama, brhh";
$divideBy = ", ";

$explodeNative = explode      ( $divideBy, $str );
$explodeMe     = explode_by_me( $divideBy, $str );

Browser other questions tagged

You are not signed in. Login or sign up in order to post.