文字列内の特定の文字を変換しますが、この関数はさまざまな方法で使用できます。
echo strtr('hello world', 'hw', 'ab'); // 第一种 aello borldecho strtr('hello world', 'hw', 'a'); // 第二种 aello worldecho strtr('hello world', ['hello' => 'hi']); // 第三种 hi worldecho strtr('hello world', ['he' => 'th', 'hello' => 'hi']); // 第四种 hi world
時間計算量
O(n)、最悪はO(n*m)です
ソースコード
ソースコードは状況に応じて一つ一つ解析されます。
1 番目と 2 番目のタイプも最も一般的に使用されますが、2 番目のタイプでは、「h」のみが「a」に変換され、「w」は処理されません。この置換方法では、短い方が優先されます。 from と to のいずれかが空の文字列の場合は、元の文字列が直接返されます。
RETURN_STR(php_strtr_ex(str, Z_STRVAL_P(from), to, MIN(Z_STRLEN_P(from), to_len)));// 从源码MIN(Z_STRLEN_P(from), to_len))可以看出来,以from、to两个字符串短的为准,剩余的会被忽略掉,所以可以解释第二种情况'w'被忽略掉 // 同理,以下to中的'b'也会被忽略掉strtr('hello world', 'h', 'ab'); // aello world
次に、php_strtr_ex メソッドと文字変換を実現する方法を主に見ていきます。ソース コードは、ハッシュ テーブルを使用して実装されます。ハッシュ テーブルは、from の各文字を to の対応する文字にマップします。
static zend_string *php_strtr_ex(zend_string *str, char *str_from, char *str_to, size_t trlen) {// trlen的值就是MIN(Z_STRLEN_P(from), to_len)) // 先构建一个hash表,用php伪代码来解释第一种情况构建好的hash表 // array('g'=>'g','h'=>'a','i'=>'i','w'=>'b')unsigned char xlat[256], j = 0;do { xlat[j] = j; } while (++j != 256);for (i = 0; i
3 番目と 4 番目の from が配列である場合、状況は 1 対 1 の文字変換ではなく、キー文字列全体を変換する文字列間の変換になります。値文字列に変換します。
3 番目のタイプである from 配列には、キーと値のペアが 1 つだけあります。実装のアイデアは、kmp アルゴリズムに従ってメイン文字列内のキー (置換された文字列) の位置を検索し、見つかった場合は値に置き換えます。 kmp 自体の効率は O(n) なので、文字列内で m 回置換されると、この場合 strtr の効率は O(n*m) になります
// 搜索被替换的字符串的所有位置e = s = ZSTR_VAL(new_str);end = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);// php_memnstr搜索 被替换的字符串 的所有位置,并替换掉for (p = ZSTR_VAL(haystack); (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) { memcpy(e, p, r - p); e += r - p; memcpy(e, str, str_len); e += str_len; (*replace_count)++; }
4 番目の方法は、さらに置換することです。配列 A 文字列による、これはさまざまな状況で最も効率的ではありません
// 先构造所有 被替换的字符串ZEND_HASH_FOREACH_STR_KEY(pats, str_key) { len = ZSTR_LEN(str_key);// 计算所有 被替换的字符串 最长和最短值if (len > maxlen) { maxlen = len; }if (len slen - pos) { len = slen - pos; }// key从maxlen循环到minlen,所以,第四种'hello'和'he',最先匹配到hellowhile (len >= minlen) {// 如果从长度hash表里面匹配到被替换的字符串里可能的长度,就从from数组里面找到替换的键值对zend_hash_str_findif ((num_bitset[len / sizeof(zend_ulong)] & (Z_UL(1)
この状況は少し複雑です。次の PHP 疑似コードは、上記の C 言語コードを変換します
$bitset = array_fill(0, 255, 0); // 首字符的hash表$num_bitset = array_fill(0, 255, 0); // key长度值的hash值$min_len = PHP_INT_MAX;$max_len = 0;$len = 0; // echo strtr('hello world', ['he' => 'th', 'hello' => 'hi']); $pats = ['he', 'hello']; foreach($pats as $v){$len = strlen($v);if($len > $max_len) {$max_len = $len; } if($len