-1

I want to replace each character from an array with one in another array:

<?php
$str="a b c d e f g h i j ";

$pattern=array();
$pattern[0]="a";
$pattern[1]="b";
$pattern[2]="c";
$pattern[3]="d";
$pattern[4]="e";
$pattern[5]="f";
$pattern[6]="g";
$pattern[7]="h";
$pattern[8]="i";
$pattern[9]="j";

$replacement=array();
$replacement[0]="6a";
$replacement[1]="6e";
$replacement[2]="6i";
$replacement[3]="6o";
$replacement[4]="6u";
$replacement[5]="5a";
$replacement[6]="5e";
$replacement[7]="5i";
$replacement[8]="5o";
$replacement[9]="5u";

echo str_replace($pattern,$replacement,$str);?>

RESULT:

    6a 66u 65o 6o 6u 5a 5e 55o 5o 5u
    a   b   c   d  e  f  g  h   i  j

the 'b' 'c' 'h' kind conflict with the others

Rajendra arora
  • 2,186
  • 1
  • 16
  • 23
Ror Schach
  • 72
  • 6

3 Answers3

2

Perhaps try strtr to replace each character:

$str = "a b c d e f g h i j ";

$replacements = [
    "a" => "6a",
    "b" => "6e",
    "c" => "6i",
    "d" => "6o",
    "e" => "6u",
    "f" => "5a",
    "g" => "5e",
    "h" => "5i",
    "i" => "5o",
    "j" => "5u",
];

echo strtr($str, $replacements);

https://3v4l.org/vugQT

Nathan
  • 11,814
  • 11
  • 50
  • 93
1

When using str_replace with arrays() as $search and $replace parameters, the function will evaluate every items in the $search array, for EACH characters of the $subject string. This is important to understand as every "loop" for a given character evaluates the content of the position of the $subject that it is working on at that point.

This results in the function being able to change that character multiple times in one pass (that character from the $subject, against all the items in the $search array.)

A simple example would be the following code/output:

$str = "a b c";
$pattern = array("a","b","a");
$replacement = array("a1","b1","c1");
echo str_replace($pattern, $replacement, $str); // Output : c11 b1 c

The function executes the "search" against ALL items in the search array, for each character in $str. Here is the first "loop" for the first character in $str ("a") :

First is finds "a", which gets replaced with "a1", then it looks for "b", which is not found. Then it looks for "a" again, and replaces the aforementioned replacement ("a"=>"a1") with the mapping "a"=>"c1" which leads to "c11".

Then goes on to the next character in $str.

YOUR EXAMPLE

When the second character in your $str ("b") is searched-against, it gets replaced with "6e" (this is the new state of $str) then following the "loop" that NEW "e" is found in the $search array, and replaced with "6u". At that point, you have "6a 66u". You can extrapolate the rest.

The reason why the first "a"=>"6a" is exact, is that the NEW state of $str after first iteration of the search "loop", that is "6a", will not match any of the other items in the search array.

As per php documentation ( php.net str_replace() ) :

Caution: Replacement order gotcha. Because str_replace() replaces left to right, it might replace a previously inserted value when doing multiple replacements.

This behavior has led to very interesting/unexpected results and was not trivial to debug.

Some answers already point to solutions, I wanted to chime-in to provide details about the experienced behavior of php.

Hope this helps, let me know! Cheers

Biospy
  • 26
  • 3
0

You need to be more exact. You could use preg_replace. The regex here is using word boundaries https://www.regular-expressions.info/wordboundaries.html.

$str="a b c d e f g h i j ";
$pattern=array();
$pattern[0]="/\ba\b/";
$pattern[1]="/\bb\b/";
$pattern[2]="/\bc\b/";
$pattern[3]="/\bd\b/";
$pattern[4]="/\be\b/";
$pattern[5]="/\bf\b/";
$pattern[6]="/\bg\b/";
$pattern[7]="/\bh\b/";
$pattern[8]="/\bi\b/";
$pattern[9]="/\bj\b/";
$replacement=array();
$replacement[0]="6a";
$replacement[1]="6e";
$replacement[2]="6i";
$replacement[3]="6o";
$replacement[4]="6u";
$replacement[5]="5a";
$replacement[6]="5e";
$replacement[7]="5i";
$replacement[8]="5o";
$replacement[9]="5u";
echo preg_replace($pattern,$replacement,$str);

https://3v4l.org/tcrHK

user3783243
  • 5,368
  • 5
  • 22
  • 41