David
David

Reputation: 2423

Make string replacements one-at-a-time using only one of each value from an array of replacements

I have a str_replace() call and I want to take values from an array, and take the next piece to replace the word "dog" with. So basically I want the $string to read:

"The duck ate the cat and the pig ate the chimp"

<?php
$string = 'The dog ate the cat and the dog ate the chimp';
$array = array('duck', 'pig');
for ($i = 0; $i < count($array); $i++) {
    $string = str_replace("dog", $array[$i], $string);
}
echo $string;
?>

This code just returns:

"The duck ate the cat and the duck ate the chimp"

I tried several things but nothing works.

Upvotes: 0

Views: 9776

Answers (6)

mickmackusa
mickmackusa

Reputation: 47991

Make solitary replacements while consuming the replacement array in a loop.

Break the loop when the replacement array runs out of values or when there are no replacements made.

If the $find value comes from an untrusted source, call preg_quote() on it before feeding it to preg_replace().

Code: (Demo)

$string = 'The dog ate the cat and the dog ate the chimp';
$find = 'dog';
$array = ['duck', 'pig'];
$count = 1;

while ($array && $count) {
    $string = preg_replace("#$find#", array_shift($array), $string, 1, $count);
}
echo $string;

Upvotes: 0

ntd
ntd

Reputation: 7434

Using substr_replace();

<?php
function str_replace_once($needle, $replace, $subject)
{
    $pos = strpos($subject, $needle);
    if ($pos !== false)
        $subject = substr_replace($subject, $replace, $pos, strlen($needle));
    return $subject;
}

$subject = 'The dog ate the cat and the dog ate the chimp';
$subject = str_replace_once('dog', 'duck', $subject);
$subject = str_replace_once('dog', 'pig', $subject);

echo $subject;
?>

Upvotes: 0

user187291
user187291

Reputation: 53940

yet one option

 $str = 'The dog ate the cat and the dog ate the chimp';
 $rep = array('duck','pig');
 echo preg_replace('/dog/e', 'array_shift($rep)', $str);

Upvotes: 0

brianreavis
brianreavis

Reputation: 11546

Edit: Sorry for the erroneous answer earlier. This'll do it. No str_replace, no preg_replace, just raw, fast string searching and splicing:

<?php
$string = 'The dog ate the cat and the dog ate the chimp';
$array = array('duck', 'pig');
$count = count($array);
$search = 'dog';
$searchlen = strlen($search);
$newstring = '';
$offset = 0;
for($i = 0; $i < $count; $i++) {
    if (($pos = strpos($string, $search, $offset)) !== false){
        $newstring .= substr($string, $offset, $pos-$offset) . $array[$i];
        $offset = $pos + $searchlen;
    }
}
$newstring .= substr($string, $offset);
echo $newstring;
?>

p.s. Not a big deal in this example, but you should keep count() outside your loop. With it where you had it, it gets executed every iteration and is slower than just calling it once beforehand.

Upvotes: 5

lemon
lemon

Reputation: 9205

<?php
$string = 'The dog ate the cat and the dog ate the chimp';
$array = array('duck', 'pig');

$count = count($array);

for($i = 0; $i < $count; $i++) {
    $string = preg_replace('/dog/', $array[$i], $string, 1);
}

echo $string;
?>

The duck ate the cat and the pig ate the chimp

Upvotes: 2

camomileCase
camomileCase

Reputation: 1706

After the first iteration of your for loop $string will have replaced both occurences of dog with duck and the following iterations will do nothing.

I can't think of a more elegant way of solving this and I hope there is something simpler possible:

<?php

$search = 'The dog ate the cat and the dog ate the chimp';
$replacements = array('duck','pig');
$matchCount = 0;
$replace = 'dog';

while(false !== strpos($search, $replace))
{
  $replacement = $replacements[$matchCount % count($replacements)];
  $search = preg_replace('/('.$replace.')/', $replacement, $search, 1);
  $matchCount++;
}

echo $search;

Upvotes: 1

Related Questions