がるの健忘録

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

str_replace()の第一&第二引数は、文字列? 配列?

結論から書くと、マニュアルに書いてある通り

search と replace が配列の場合、str_replace() は各配列から値をひとつ取り出し、 subject 上で検索と置換を行うために使用します。

なのですが……ちょっと驚いたので。


端的には、以下のコード。

<?php

$s = 'abc';

$r = str_replace(['a', 'b', 'c'], ['ca', 'cb', 'cc'], $s, $count);
var_dump($r, $count);

$r = str_replace(['c', 'a', 'b'], ['cc', 'ca', 'cb'], $s, $count);
var_dump($r, $count);


結果

string(8) "ccaccbcc"
int(5)
string(6) "cacbcc"
int(3)

配列の順番を変えると、結果が変わるんだねぇ………。
変換後の値がかぶらなければ順番は気にしなくてよいと思うのですが、変換後の値が「別の変換前の値」とかぶる場合、順番を気にする必要があるっぽです。
ただ「順番にやる」事が保証されるのであれば(マニュアルに書いてあるし)、それはそれで使い道が色々と別角度からは増えそうだなぁ、と。


で、少し疑問「だとすると、変換する配列の1組ごとに、全件一致検索毎回流しまくってるのかなぁ?」と。
ソースコード読むの面倒なんで、一端外側から叩いて、軽く確認。

<?php

$s = 'abc';

$t = microtime(true);
for($i = 0; $i < 100000; ++$i) {
    $r = str_replace(['c', 'a', 'b'], ['cc', 'ca', 'cb'], $s);
}
$t2 = microtime(true);
var_dump($t2 - $t);

$t = microtime(true);
for($i = 0; $i < 100000; ++$i) {
    $r = str_replace('c', 'cc', $s);
    $r = str_replace('a', 'ca', $r);
    $r = str_replace('b', 'cb', $r);
}
$t2 = microtime(true);
var_dump($t2 - $t);


結果

[gallu@hogehoge48 ~]$ php t.php
float(0.058500051498413)
float(0.056888103485107)
[gallu@hogehoge48 ~]$ php t.php
float(0.064057111740112)
float(0.06181788444519)
[gallu@hogehoge48 ~]$ php t.php
float(0.066102027893066)
float(0.065979957580566)
[gallu@hogehoge48 ~]$ php t.php
float(0.086111068725586)
float(0.082880973815918)
[gallu@hogehoge48 ~]$ php t.php
float(0.070822954177856)
float(0.057141065597534)

………ぶも??
予想としては「関数callのオーバヘッド分、少しだけ分割したほうが遅いけど誤差範囲」だと思ったのに……誤差範囲程度とはいえ「配列より文字列で複数回callしたほうが早い」???
あらら…てっきり「配列で渡したほうが効率よく文字列操作してくれる」と思ってたんですけどねぇ。


これは、今後少し、使い方を改めたほうがよいかしらん?