Explode () 'manual' in PHP

4

Just because of the challenge and the pleasure of programming I'm trying to recreate the explode() function 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 our $divideBy has more than one char, eg:

$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 realize why this happens, in this case, because we are comparing a single char ( $str[$i] ) to a set of chars (","). Teitei bypass this by changing the condition within our cycle:

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

But that also does not work:

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 realize that this happens because we are creating a new element in the array for every char of $divideBy .

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

    
asked by anonymous 26.06.2015 / 13:09

2 answers

2

Just like you said, the problem is that you're comparing a single char with a char set. You can resolve this as follows:

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

The above statement does the following from the inside out:

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

Then combining these two functions, you can get the desired result, ie read the current string and see if the position 0 , ie first character, is your divider, if it is, skip the amount of characters of the divisor size.

So there are several ways to do this, here is one that I find 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"
  }

*/
    
26.06.2015 / 14:07
1

You must also use 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 );
    
26.06.2015 / 13:18