1

I need to replace the word 'me' with the word 'you', and the word 'you' with the 'me' simultaneously. It works with strtr() when the 2 words aren't next to each other, but when they are, it replaces the first word, then ignores the second word. Is there any way to fix this?

<?php

$string = "tell me you want to get it right";
$string = trim(strtr(" ".trim($string)." ", array(
" me " => " you ",
" you " => " me "
)));

echo $string;

?>

Actual Result:

tell you you want to get it right

Need Result:

tell you me want to get it right

PS: Don't really want any answers that uses something like "Replace all 'you's with 'you1234', and then all 'me's with 'me1234', then just replace all 'you1234's with 'me', and all 'me1234's with 'you'.

frosty
  • 2,559
  • 8
  • 37
  • 73
  • 1
    [unhelpful comment] I'm curious why you want simultaneity. Is this just an academic question, or is there a real use case? – Mitya May 16 '16 at 20:57

3 Answers3

2

This seems to work, whether the words are sequential or separated.

$str = "foo something bar";
echo preg_replace_callback(
    '/\b(foo|bar)\b/',
    function($match) { return $match[0] == 'foo' ? 'bar' : 'foo'; },
    $str
);

It's not really simultaneous; the callback loops over the matches. However, the replacements are seemingly done on the original string, not a temporary one that is updated after each callback (avoiding your "you you" example), so it's basically the same thing.

Mitya
  • 33,629
  • 9
  • 60
  • 107
  • Is there a way to convert this to kind of like the strtr() function? Where you can replace multiple words with each other at once, with the array? This seems to work only for one words at a time. – frosty May 16 '16 at 21:09
  • Also, I'm kind of curious, since in the question, I was asking about when the 2 words are next to each other, it won't work. But your example, uses 2 words that are at the exact opposite ends of each other. – frosty May 16 '16 at 21:10
  • Not sure of the mechanics, but it seems to work whether they're next to each other or not. As I mentioned, this presumably means the replacement is done on a temporary version of the original string, stored in memory, rather than the iterative, updated string (which would lead to the problem you found with `strtr`. Can't see a way to do this with `strtr`. – Mitya May 17 '16 at 10:48
2

How about using an anonymous function with an array? Any excuse to use an anonymous function, makes me happy :)

$string = "tell me you want to get it right";
$string = implode(" ", array_map(function($word, $swap = ["me", "you"]) {
    return ($index = array_search($word, $swap)) === false
        ? $word : $swap[++$index % 2];
}, explode(" ", $string)));
var_dump($string);
/* string 'tell you me want to get it right' (length=32) */

Or for more complicated replacements

$string = "tell me you want to get it right";
$replacements = ["me" => "you", "you" => "me", "right" => "wrong"];
$string = implode(" ", array_map(function($word) use($replacements) {
    return isset($replacements[$word]) ? $replacements[$word] : $word;
}, explode(" ", $string)));
var_dump($string);
/* string 'tell you me want to get it wrong' (length=32) */
Matt Raines
  • 4,149
  • 8
  • 31
  • 34
  • OH! This is awesome. The perfect function. I definitely need to look up anonymous functions, and how to go about making them. They seem really useful. – frosty May 17 '16 at 18:06
0

This is kinda (on some way, because of using of cheap trick)

Replace all 'you's with 'you1234', and then all 'me's with 'me1234'

answer...but, it should work. It is function, string and replacement (associative) array are arguments. It should work for multiple replacements, simultaneously. Position of strings is not matter.

function replace_sim($str, $replace) {

  $arr = str_word_count($str, 1);
  $keys = array();
  $real_val = array();
  for ($i = 0; $i < count($arr); $i++) {

    foreach($replace as $key => $value) {
      if ($arr[$i] == $key) {
        $arr[$i] = strrev($value);

        $keys[] = $i;
        $real_val[] = $value;
      }
    }

  }
  $i = -1;
  foreach($keys as $key) {
    $i++;
    $arr[$key] = $real_val[$i];
  }

  $str = join(' ', $arr);
  return $str;
}

//usage
$string = "tell me you want to you get it right me you";
$replace=array('me'=>'you','you'=>'me','get'=>'it','it'=>'get');
echo replace_sim($string,$replace);

echo '<br>';

$string = "tell me i want you";
$replace=array('me'=>'you','you'=>'me');
echo replace_sim($string,$replace);
sinisake
  • 11,240
  • 2
  • 19
  • 27