6

I've been using the recurisve SpinTax processor as seen here, and it works just fine for smaller strings. However, it begins to run out of memory when the string goes beyond 20KB, and it's becoming a problem.

If I have a string like this:

{Hello|Howdy|Hola} to you, {Mr.|Mrs.|Ms.} {Smith|Williams|Austin}!

and I want to have random combinations of the words put together, and not use the technique as seen in the link above (recursing through the string until there are no more words in curly-braces), how should I do it?

I was thinking about something like this:

$array = explode(' ', $string);
foreach ($array as $k=>$v) {
        if ($v[0] == '{') {
                $n_array = explode('|', $v);
                $array[$k] = str_replace(array('{', '}'), '', $n_array[array_rand($n_array)]);
        }
}
echo implode(' ', $array);

But it falls apart when there are spaces in-between the options for the spintax. RegEx seems to be the solution here, but I have no idea how to implement it and have much more efficient performance.

Thanks!

David
  • 3,831
  • 2
  • 28
  • 38

2 Answers2

10

You could create a function that uses a callback within to determine which variant of the many potentials will be created and returned:

// Pass in the string you'd for which you'd like a random output
function random ($str) {
    // Returns random values found between { this | and }
    return preg_replace_callback("/{(.*?)}/", function ($match) {
        // Splits 'foo|bar' strings into an array
        $words = explode("|", $match[1]);
        // Grabs a random array entry and returns it
        return $words[array_rand($words)];
    // The input string, which you provide when calling this func
    }, $str);
}

random("{Hello|Howdy|Hola} to you, {Mr.|Mrs.|Ms.} {Smith|Williams|Austin}!");
random("{This|That} is so {awesome|crazy|stupid}!");
random("{StackOverflow|StackExchange} solves all of my {problems|issues}.");
Sampson
  • 265,109
  • 74
  • 539
  • 565
  • Thanks so much! As said in the Madara's answer's comments, this took me from memory errors to .0002590 seconds to process a 40KB file. Amazing! Thanks – David Nov 20 '12 at 19:09
3

You can use preg_replace_callback() to specify a replacement function.

$str = "{Hello|Howdy|Hola} to you, {Mr.|Mrs.|Ms.} {Smith|Williams|Austin}!";

$replacement = function ($matches) {
    $array = explode("|", $matches[1]);
    return $array[array_rand($array)];
};

$str = preg_replace_callback("/\{([^}]+)\}/", $replacement, $str);
var_dump($str);
Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
  • I love this solution. It took .0002592 seconds to run this, and the old method got an `Allowed memory size of 134217728 bytes exhausted (tried to allocate 74087 bytes)` error. Excellent! – David Nov 20 '12 at 18:55
  • 2
    I really do appreciate this answer - it really helped. However, Johnathan Sampson got to it first. Thanks so much! – David Nov 20 '12 at 19:09