PHP reemplaza una palabra aleatoria de una cadena

Quiero reemplazar una palabra aleatoria de las cuales hay varias en una cadena.

Así que digamos que la cadena es

$str = 'I like blue, blue is my favorite colour because blue is very nice and blue is pretty';

Y digamos que quiero reemplazar la palabra azul con rojo pero solo 2 veces en posiciones aleatorias.

Entonces, después de que se realiza una función, la salida podría ser como

I like red, blue is my favorite colour because red is very nice and blue is pretty

Otro podría ser

I like blue, red is my favorite colour because blue is very nice and red is pretty

Entonces quiero reemplazar la misma palabra varias veces pero cada vez en diferentes posiciones.

Pensé en usar preg_match pero eso no tiene la opción de que la posición de las palabras reemplazadas por orina también sea aleatoria.

¿Alguien tiene idea de cómo lograr esto?

preguntado el 22 de mayo de 12 a las 15:05

4 Respuestas

Por mucho que deteste usar expresiones regulares para algo que a primera vista es muy simple, para garantizar exactamente n reemplaza Creo que puede ayudar aquí, ya que permite usar fácilmente array_rand(), que hace exactamente lo que quieres: elige n elementos aleatorios de una lista de longitud indeterminada (MEJORADO).

<?php

    function replace_n_occurences ($str, $search, $replace, $n) {

        // Get all occurences of $search and their offsets within the string
        $count = preg_match_all('/\b'.preg_quote($search, '/').'\b/', $str, $matches, PREG_OFFSET_CAPTURE);

        // Get string length information so we can account for replacement strings that are of a different length to the search string
        $searchLen = strlen($search);
        $diff = strlen($replace) - $searchLen;
        $offset = 0;

        // Loop $n random matches and replace them, if $n < 1 || $n > $count, replace all matches
        $toReplace = ($n < 1 || $n > $count) ? array_keys($matches[0]) : (array) array_rand($matches[0], $n);
        foreach ($toReplace as $match) {
            $str = substr($str, 0, $matches[0][$match][1] + $offset).$replace.substr($str, $matches[0][$match][1] + $searchLen + $offset);
            $offset += $diff;
        }

        return $str;

    }

    $str = 'I like blue, blue is my favorite colour because blue is very nice and blue is pretty';

    $search = 'blue';
    $replace = 'red';
    $replaceCount = 2;

    echo replace_n_occurences($str, $search, $replace, $replaceCount);

Verlo funcionando

contestado el 22 de mayo de 12 a las 16:05

echo preg_replace_callback('/blue/', function($match) { return rand(0,100) > 50 ? $match[0] : 'red'; }, $str);

contestado el 22 de mayo de 12 a las 16:05

¿Esto no reemplazaría 2 ocurrencias aleatorias de "azul", sino que daría un 50% de posibilidades de reemplazar cada ocurrencia de azul? - bien

Sí, pero puede usar un contador para dejar de reemplazar después de 2 veces. - Eugene

Bueno, podrías usar este algoritmo:

  1. calcule la cantidad aleatoria de veces que desea reemplazar la cadena
  2. explotar la cadena en una matriz
  3. para esa matriz, reemplace la ocurrencia de la cadena solo si un valor aleatorio entre 1 y 100 es % 3 (por ejemplo)
  4. Disminuya el número calculado en el punto 1.
  5. Repita hasta que el número llegue a 0.

contestado el 22 de mayo de 12 a las 15:05

<?php
$amount_to_replace = 2;
$word_to_replace = 'blue';
$new_word = 'red';

$str = 'I like blue, blue is my favorite colour because blue is very nice and blue is pretty';

$words = explode(' ', $str); //convert string to array of words
$blue_keys = array_keys($words, $word_to_replace); //get index of all $word_to_replace

if(count($blue_keys) <= $amount_to_replace) { //if there are less to replace, we don't need to randomly choose.  just replace them all
    $keys_to_replace = array_keys($blue_keys);
}
else {
    $keys_to_replace = array();
    while(count($keys_to_replace) < $amount_to_replace) { //while we have more to choose
        $replacement_key = rand(0, count($blue_keys) -1);
        if(in_array($replacement_key, $keys_to_replace)) continue; //we have already chosen to replace this word, don't add it again
        else {
            $keys_to_replace[] = $replacement_key;
        }
    }
}

foreach($keys_to_replace as $replacement_key) {
    $words[$blue_keys[$replacement_key]] = $new_word;
}

$new_str = implode(' ', $words); //convert array of words back into string
echo $new_str."\n";
?>

NB: acabo de darme cuenta de que esto no reemplazará el primer azul, ya que se ingresa en la matriz de palabras como "azul" y, por lo tanto, no coincide con la llamada array_keys.

contestado el 22 de mayo de 12 a las 16:05

eso sería genial si eso pudiera manejar $ n reemplazos - Matías Dunnowa

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.