2

I've researched and need to find the best way to replace a need with an array of possibilities randomly.

ie:

$text = "Welcome to [city]. I want [city] to be a random version each time. [city] should not be the same [city] each time.";

$keyword = "[city]";
$values = array("Orlando", "Dallas", "Atlanta", "Detroit", "Tampa", "Miami");

$result = str_replace("[$keyword]", $values, $text);

The result is every occurrence has "Array" for city. I need to replace all of the city occurrences with a random from $values. I want to do this the cleanest way possible. My solution so far is terrible (recursive). What is the best solution for this? Thank you!

Paul
  • 139,544
  • 27
  • 275
  • 264
Kris B.
  • 95
  • 1
  • 8

6 Answers6

7

You can use preg_replace_callback to execute a function for each match and return the replacement string:

$text = "Welcome to [city]. I want [city] to be a random version each time. [city] should not be the same [city] each time.";

$keyword = "[city]";
$values = array("Orlando", "Dallas", "Atlanta", "Detroit", "Tampa", "Miami");

$result = preg_replace_callback('/' . preg_quote($keyword) . '/', 
  function() use ($values){ return $values[array_rand($values)]; }, $text);

Sample $result:

Welcome to Atlanta. I want Dallas to be a random version each time. Miami should not be the same Atlanta each time.

Paul
  • 139,544
  • 27
  • 275
  • 264
  • This does not guarantee: "_should not be the same_". This solution may randomly print the same city in the same block of text. – mickmackusa Jan 03 '22 at 14:44
5

You could use preg_replace_callback with array_rand

<?php
$text = "Welcome to [city]. I want [city] to be a random version each time. [city] should not be the same [city] each time.";

$values = array("Orlando", "Dallas", "Atlanta", "Detroit", "Tampa", "Miami");

$result = preg_replace_callback("/\[city\]/", function($matches) use ($values) { return $values[array_rand($values)]; }, $text);

echo $result;

Example here.

Hamish
  • 22,860
  • 8
  • 53
  • 67
  • This does not guarantee: "_should not be the same_". This solution may randomly print the same city in the same block of text. – mickmackusa Jan 03 '22 at 14:45
1

Here's another idea

$text = "Welcome to [city]. I want [city] to be a random version each time. [city] should not be the same [city] each time.";

$pattern = "/\[city\]/";
$values = array("Orlando", "Dallas", "Atlanta", "Detroit", "Tampa", "Miami");

while(preg_match($pattern, $text)) {
        $text = preg_replace($pattern, $values[array_rand($values)], $text, 1);
}

echo $text;

And some output:

Welcome to Orlando. I want Tampa to be a random version each time. Miami should not be the same Orlando each time.
  • This does not guarantee: "_should not be the same_". This solution may randomly print the same city in the same block of text. – mickmackusa Jan 03 '22 at 14:45
0

You're replacing a text using $values which is an array, so the result is just the word "Array". The replacement should be a string.

You can use array_rand() to pick random entries from your array.

$result = str_replace($keyword, $values[array_rand($values)], $text);

The result is something like this:

Welcome to Atlanta. I want Atlanta to be a random version each time. Atlanta should not be the same Atlanta each time.
Welcome to Orlando. I want Orlando to be a random version each time. Orlando should not be the same Orlando each time.

If you want the city to be random each line, check @PaulP.R.O's answer.

flowfree
  • 16,356
  • 12
  • 52
  • 76
  • "[city] should not be the same [city] each time" – Hamish Jun 11 '12 at 02:34
  • Thanks, rour solution works great for the same replacement. However, I needed to have variable replacements in one go throughout the entire document. :) – Kris B. Jun 11 '12 at 02:43
0

If:

  1. the four city placeholders that are randomly selected should not repeat within your 3-sentence string and
  2. you don't mind mutating the input array and
  3. you will always have enough values to accommodate all of the placeholders, then:

You can pass the array into the custom function scope as a reference variable. This means that as you access and remove values via array_pop(), it will be impossible to encounter the same city twice. You only need to shuffle() the input array once before performing the replacements.

Code: (Demo)

$text = "Welcome to [city]. I want [city] to be a random version each time. [city] should not be the same [city] each time.";

$keyword = "[city]";
$values = ["Orlando", "Dallas", "Atlanta", "Detroit", "Tampa", "Miami"];
shuffle($values);

echo preg_replace_callback(
         '/' . preg_quote($keyword) . '/',
         function() use(&$values) { return array_pop($values); },
         $text
     );

Potential outputs:

Welcome to Detroit. I want Tampa to be a random version each time. Dallas should not be the same Orlando each time.

or

Welcome to Orlando. I want Miami to be a random version each time. Atlanta should not be the same Detroit each time.

or

Welcome to Atlanta. I want Tampa to be a random version each time. Orlando should not be the same Dallas each time.

etc.


Obeying the same rules as initially described at the top of this answer, it will be easier to read and maintain an approach which does not leverage regex. Simply shuffle the array, replace the square-brace placeholders with placeholders that the printf() family if functions can recognize, then feed the entire shuffled array to vprintf().

This has the added benefit of not mutating/consuming the original array via array_pop(). (Demo)

shuffle($values);
vprintf(
    str_replace(
         $keyword,
         '%s',
         $text
    ),
    $values
);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
-1

try this http://codepad.org/qp7XYHe4

<?
$text = "Welcome to [city]. I want [city] to be a random version each time. [city] should not be the same [city] each time.";

$keyword = "[city]";
$values = array("Orlando", "Dallas", "Atlanta", "Detroit", "Tampa", "Miami");

echo $result = str_replace($keyword, shuffle($values)?current($values):$values[0], $text);
Pramendra Gupta
  • 14,667
  • 4
  • 33
  • 34
  • Doesn't work, because "[city] should not be the same [city] each time". This uses the same value for each replacement. – Hamish Jun 11 '12 at 02:35