以下のコードが機能します。
$string = "This is a very [adjective] [noun], and this is a [adjective] [noun]."
function replace_word ( $matches )
{
$replaces = array(
'[adjective]' => array("big", "small", "good", "bad"),
'[noun]' => array("house", "dog", "car")
);
return $replaces[$matches[0]][array_rand($replaces[ $matches[0] ])];
}
echo preg_replace_callback("(\[.*?\])", "replace_word", $string);
まず、[something]
単語の一部で正規表現の一致を行い、でreplace_word()
コールバック関数を呼び出しますpreg_replace_callback()
。この関数には、内部に$replaces
2次元の深い配列が定義されており、各行は[word type] => array('rep1', 'rep2', ...)
フォーマットで定義されています。
トリッキーで少しわかりにくい行はreturn $replaces[$matches[0]][array_rand($replaces[ $matches[0] ])];
です。私がそれを少しチャンクすると、それはあなたにとってはるかに解析可能になるでしょう:
$random = array_rand( $replaces[ $matches[0] ] );
$matches[0]
は単語タイプです。これは、$replaces
検索している配列のキーです。これは、元の文字列の正規表現によって見つかりました。array_rand()
基本的に、配列の1つの要素を選択し、その数値インデックスを返します。したがって、現在は、置換を含む配列のとの$random
間のどこかに整数があります。0
(number of elements - 1)
return $replaces[ $matches[0] ][$random];
$random
これにより、replace配列からth要素が返されます。コードスニペットでは、これらの2行が1行にまとめられています。
1つの要素を1回だけ表示する
分離した要素(2つの形容詞または名詞を2回繰り返さない)が必要な場合は、別のトリックを実行する必要があります。$replaces
関数の内部ではなく、関数の外部で定義されるように配列を設定しreplace_word()
ます。
$GLOBALS['replaces'] = array(
'[adjective]' => array("big", "small", "good", "bad"),
'[noun]' => array("house", "dog", "car")
);
関数内で、を呼び出して、ローカル$replaces
変数を新しく設定された配列への参照として設定し$replaces = &$GLOBALS['replaces'];
ます。(&
演算子はこれを参照として設定するため、(要素の削除や追加など)行うすべてのことで$replaces
元の配列も変更されます。これがないと、コピーになります。)
そして、回線に到着する前に、現在返却されるキーreturn
を呼び出します。unset()
unset($replaces[$matches[0]][array_rand($replaces[ $matches[0] ])]);
まとめた関数は次のようになります。
function replace_word ( $matches )
{
$replaces = &$GLOBALS['replaces'];
unset($replaces[$matches[0]][array_rand($replaces[ $matches[0] ])]);
return $replaces[$matches[0]][array_rand($replaces[ $matches[0] ])];
}
また、$replaces
はグローバルへの参照であるためunset()
、元の配列も更新されます。の次の呼び出しでreplace_word()
は、同じ置換が再び見つかりません。
配列のサイズに注意してください!
存在する置換値の量よりも多くの置換変数を含む文字列は、未定義のインデックス E_NOTICE
をスローします。次の文字列は機能しません。
$string = "This is a very [adjective] [noun], and this is a [adjective] [noun]. This is also an [adjective] [noun] with an [adjective] [noun].";
出力の1つは次のようになり、可能な置換が不足していることを示しています。
これはとても大きな家で、これは大きな家です。これも小さいです。