3

I have a sentence that needs to randomly change parts that are in the curly braces. The important part is that the values inside the braces can change (as in you could put any word in there), so

$x = '{Please,|Just|If you can,} make so, that this 

{incredible|cool|simple|important|useless} sentence {fast|correctly|instantly} 

changed randomly every time'; //this is the string that needs to be broken up

When I use

$parts = explode('{', $x); 

it gives me an array that looks like this

array ([0]=>[1]=>{Please,|Just|If you can,} make so, that this [2]=>incredible|cool|simple|important|useless} sentence [3]=>fast|correctly|instantly} changed randomly every time)

which doesn't work.

What I've done is:

 $parts = [

  ['Please,','Just','If you can,'], 

  ['incredible', 'cool','simple','important','useless'],

  ['fast','correctly','instantly'],

];

$p = [];

foreach ($parts as $key => $values) {

  $index = array_rand($values, 1);

  $p[$key] = $values[$index];
}


  $x_one = $p[0] . ' make it so that ' .  $p[1] . ' this sentence

changed ' . $p[2] . ' randomly every time.';

echo $x_one;  

I have to get $parts from $x, because the words in the string $x can change. Don't know where to go from here.

4 Answers 4

4

You can use preg_replace_callback() to catch the sequence, split using | and return a random value:

$x = '{Please,|Just|If you can,} make so, that this

{incredible|cool|simple|important|useless} sentence {fast|correctly|instantly}

changed randomly every time';

// catch all strings that match with {...}
$str = preg_replace_callback('~\{([^}]+)\}~', function($matches){
    // split using |
    $pos = explode('|', $matches[1]);
    // return random element
    return $pos[array_rand($pos)];
}, $x);

echo $str;

Possible outputs:

  • If you can, make so, that this cool sentence correctly changed randomly every time
  • Please, make so, that this cool sentence fast changed randomly every time
  • If you can, make so, that this incredible sentence fast changed randomly every time

Regular expression:

\{       # { character
 (       # capture group
 [^}]+   # all character until }
 )       # end capture group
\}       # } character
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! I've never used preg_replace_callback() before. And thank you for the explanation. I needed it
1

Another approch can looks like this :

    $output = $input = '{Please,|Just|If you can,} make so, that this 

{incredible|cool|simple|important|useless} sentence {fast|correctly|instantly} 

changed randomly every time';


/**
 * Will output
 *  0 => string '{Please,|Just|If you can,}' (length=26)
 * 1 => string '{incredible|cool|simple|important|useless}' (length=42)
 * 2 => string '{fast|correctly|instantly}' (length=26)
 */
preg_match_all('/\{([^}]+)\}/',$input,$m);
foreach ($m[1] as $index => $rotateWord) {
    $words = explode('|',$rotateWord); //Split by pipe each words founds
    $randomWord = $words[rand(0, count($words) - 1)]; // Select random word.
    $output = str_replace($m[0][$index], $randomWord, $output);
}

var_dump($output);

Comments

1

Regex can be extremely useful in these cases. It's used, for instance, in parsers to find the tokens.

In this case you want to get all substrings between curly braces. This does the trick:

$matches = array();
preg_match_all('/\{([^}]*)\}/', $x, $matches);
print_r($matches);

Output:

Array
(
    [0] => Array
        (
            [0] => {Please,|Just|If you can,}
            [1] => {incredible|cool|simple|important|useless}
            [2] => {fast|correctly|instantly}
        )

    [1] => Array
        (
            [0] => Please,|Just|If you can,
            [1] => incredible|cool|simple|important|useless
            [2] => fast|correctly|instantly
        )
)

The expression '/\{([^}]*)\}/ means:

  • /: this could be any character
  • \{: start with start curly brace
  • ([^}]+): everything that is not an end curly brace (the parentheses are used to isolate the matched expression, that's why the result is in the index number 1 of an array)
  • \}: end with an end curly brace
  • /: it must be the same as the first character

In other words: anything between curly braces.

You can test regular expressions at https://regex101.com/ or at https://regexr.com/.

But that's not enough: you want to replace those matches. preg_replace can do that, but it's also not enough, because you also need to call some function to select a random substring. preg_replace_callback can do that.

<?php

$x = '{Please,|Just|If you can,} make so, that this 

{incredible|cool|simple|important|useless} sentence {fast|correctly|instantly} 

changed randomly every time';

echo preg_replace_callback(
    '/\{([^\}]+)\}/',
    function ($matches) {
        $options = explode('|', $matches[1]);
        return $options[array_rand($options)];
    },
    $x
);

1 Comment

Thank you for all of the helpful information, I really appreciate it.
0

If the values inside the braces can change, it is, in fact, better to extract them from the template into arrays, as you have done in the question. Having parts array and template string, you then can use array_map alongside with strtr:

$parts = [
  '%part1%' => ['Please,','Just','If you can,'], 

  '%part2%' => ['incredible', 'cool','simple','important','useless'],

  '%part3%' => ['fast','correctly','instantly'],
];

$template = '%part1% make so, that this %part2% sentence %part3% changed randomly every time';

$result = strtr($template, array_map(function ($values) {
    return $values[array_rand($values, 1)];
}, $parts));

Here is the demo.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.