OneNerd OneNerd - 5 months ago 11
PHP Question

Efficient Way to Create Keywords from String

So, I have a phrase like this:

one_two_three_four


.. and for clarity, it could be something like this too:

one_two_three_four_five_six_seven_eight_nine_ten_eleven_twelve


.. but for purposes of brevity, I am just going to use this one as an example:

one_two_three_four


From the string, I want to create the following keywords

one
one_two
one_two_three
two
two_three
two_three_four
three
three_four
four


I am looking for the most efficient way (in PHP) to parse out strings like this (some will be much larger).

I can get this far:

$keyword = explode('_', $string);


So now I have an array like this:

one
two
three
four


I am stuck on how to get from the original string into the variants.

Answer

First thing you need to explode the string by _

$str = 'one_two_three_four_five_six';
$array = explode('_', $str);

Add an empty array to store result there

$result = [];

Define a recursive function that takes an array, implode array values, remove last element and recall the same array until length is 0

function visitArray($array, &$result) {
    if(count($array) == 0) //Check if length is 0 (Stop executing)
        return;
    $result[] = implode('_', $array); //Implode array values
    return visitArray(array_slice($array, 0, count($array) -  1), $result); //Remove last element and call again the same function
}

So if you pass [1, 2, 3] to visitArray you will have 1_2_3, 1_2, 1 in the result array.

Now you need a secondary function to call visitArray with a new position,

That means, if we have this array [1, 2, 3]

we need to call visitArray [1,2,3], [2,3], [3]

So we define a function with simple for loop to iterate around array values, and each time we call visitArray() and we ignore the called once by using array_slice with position variable.

function callVisit($array, &$result, $position = 0) {
    for($i = 0; $i < count($array); $i++)
        visitArray(array_slice($array, $position++, count($array) - 1), $result);
}

Update: If you need to remove the position param you could replace the forloop with list as below:

function callVisit($array, &$result) {
    while (list(,$v) = each($array)) 
    { 
        visitArray($array, $result);
        array_shift($array); //Remove first element
    } 
}

So you need to call callVisit() by passing two params, the array, result array (where result should be stored)

callVisit($array, $result);

Full code:

<?php

$str = 'one_two_three_four_five_six';

$array = explode('_', $str);

$result = [];


function callVisit($array, &$result, $position = 0) {
    for($i = 0; $i < count($array); $i++) 
        visitArray(array_slice($array, $position++, count($array) - 1), $result);
}

function visitArray($array, &$result) {
    if(count($array) == 0)
        return;
    $result[] = implode('_', $array);
    return visitArray(array_slice($array, 0, count($array) -  1), $result);
}


callVisit($array, $result);

echo "<pre>", json_encode($result, JSON_PRETTY_PRINT), "</pre>";
Comments