1

I'm trying to replace the characters (numbers and letters) in a string. When I try the "php" way, it gives the wrong result for some of the characters. Why?

PHP-WAY:

$find = array( "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f" );
$replace = array( "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p" );
$haystack = "a5c9a06bfacf5f12cf01ab3f202f6c78"

//This incorrectly returns: kpmjkkglpkmppplmmpklklnpmkmpgmhi
echo str_replace( $find, $replace, $haystack );

LOOP WAY:

$find = array( "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f" );
$replace = array( "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p" );
$haystack = "a5c9a06bfacf5f12cf01ab3f202f6c78"

//This correctly returns: kfmjkaglpkmpfpbcmpabkldpcacpgmhi
$newStr = "";
$chars = str_split( $haystack );
for ( $i = 0, $length = count( $chars ); $i < $length; $i++ )
{
    $newStr .= $replace[ array_search( $chars[ $i ], $find ) ];
}
echo $newStr;

Why is the first one incorrect? Am I using it wrong?

2
  • 1
    Order of entries in your arrays.... str_replace() will process each array entry in the order they appear in your array, so if a '1' gets replaced with 'b', then that 'b' will subsequently get replaced with 'l'; use strtr() (uk3.php.net/manual/en/function.strtr.php) rather than str_replace() if you want to prevent that behaviour Commented May 28, 2013 at 22:45
  • Thanks, added as answer below! Commented May 28, 2013 at 22:48

3 Answers 3

3

Order of entries in your arrays.... str_replace() will process each array entry in the order they appear in your array, so if a '1' gets replaced with 'b', then that 'b' will subsequently get replaced with 'l'; use strtr() rather than str_replace() if you want to prevent that behaviour.

$find = array( "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f" );
$replace = array( "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p" );
$haystack = "a5c9a06bfacf5f12cf01ab3f202f6c78" ;
echo strtr($haystack, array_combine($find, $replace));

Your own code only does a single replace because it's looping against your string, not against the from/to arrays.

Sign up to request clarification or add additional context in comments.

1 Comment

Can you please add in the sample code (that I added in my answer)? Then i'll mark yours as the answer. Thanks.
1

Just use strtr

$haystack = "a5c9a06bfacf5f12cf01ab3f202f6c78" ;
echo strtr($haystack, implode($find), implode($replace));

Or preg_replace_callback

$find = array_flip($find);
echo preg_replace_callback('/[a-f0-9]/', function ($v) use($replace, $find) {
    return $replace[$find[$v[0]]];
}, $haystack);

Output

kfmjkaglpkmpfpbcmpabkldpcacpgmhi 

Comments

0

As specified by @MarkBaker, the answer is that str_replace does not simply move forward in the string, but instead works like a recursive .replace(). Instead, use strtr (which is equivalent to Linux tr command:

$tr = array( "0" => "a","1" => "b","2" => "c","3" => "d","4" => "e","5" => "f","6" => "g","7" => "h","8" => "i","9" => "j","a" => "k","b" => "l","c" => "m","d" => "n","e" => "o","f" => "p" );
$haystack = "a5c9a06bfacf5f12cf01ab3f202f6c78"

echo strtr( $haystack, $tr );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.