1

[]角かっこ( )内のすべての文字列を、その文字列という名前の配列からランダムに選択された項目に置き換えたいと思います。

これはこの問題と非常に似ていますが、異なるブラケットの内容をその名前の配列の文字列に置き換えたいという点でひねりがあります。

例を使用すると、これが少し明確になります。

だから私は文字列を持っていると言う

"This is a very [adjective] [noun], and this is a [adjective] [noun]."

そして変数:

$adjective = array("big","small","good","bad");
$noun      = array("house","dog","car");

そして"This is a very big house, and this is a good dog."、ランダムに選択することで、それが戻ってくるかどうかを確認します。つまり、それぞれ[string]を。という名前の配列からランダムに選択されたアイテムに置き換えるPHP関数を作成したいと思い$stringます。今のところ、ランダムに選択することで繰り返し選択するかどうかは問題ではありませんが、[]アイテムごとに新しい選択を行う必要があります。

これを明確に説明できたと思います。あなたが私が達成しようとしていることを手に入れ、それを行うためのより良い方法を考えることができれば、私は非常に感謝するでしょう。

4

5 に答える 5

8

アルゴリズム

  1. この正規表現に一致:(\[.*?\])
  2. マッチグループごとに、関連する配列からアイテムを選択します。
  3. 文字列を順番に置き換えます。

実装

$string    = "This is a very [adjective] [noun], and this is a [adjective] [noun].";
$adjective = array("big","small","good","bad");
$noun      = array("house","dog","car");

// find matches against the regex and replaces them the callback function.
$result    = preg_replace_callback(

                 // Matches parts to be replaced: '[adjective]', '[noun]'
                 '/(\[.*?\])/',

                 // Callback function. Use 'use()' or define arrays as 'global'
                 function($matches) use ($adjective, $noun) {

                     // Remove square brackets from the match
                     // then use it as variable name
                     $array = ${trim($matches[1],"[]")};

                     // Pick an item from the related array whichever.
                     return $array[array_rand($array)];
                 },

                 // Input string to search in.
                 $string
             );

print $result;

説明

preg_replace_callback関数は、提供されたコールバック関数を使用して正規表現の検索と置換を実行します。

  • 最初のパラメーターは、一致する正規表現です(スラッシュで囲まれています)。/(\[.*?\])/

  • 2番目のパラメーターは、一致ごとに呼び出すコールバック関数です。現在の一致をパラメーターとして受け取ります。

    • use()関数内から配列にアクセスするには、ここを使用するか、配列をグローバルとして定義する必要がありますglobal $adjective = ...。つまり、次のいずれかを実行する必要があります。

      a)配列を次のように定義しますglobal

        ..。
        グローバル$adjective= array( "big"、 "small"、 "good"、 "bad");
        グローバル$noun= array( "house"、 "dog"、 "car");
        ..。
        function($ matches){
        ..。
      

      b)使用use

        ..。
        $ adjective = array( "big"、 "small"、 "good"、 "bad");
        $ noun = array( "house"、 "dog"、 "car");
        ..。
        function($ matches)use($ ajective、$ noun){
        ..。
      
    • コールバック関数の最初の行:

      • トリム[]:関数を使用して、一致から角かっこ()を削除しますtrim

      • $ {}:一致名を持つ配列名として使用する変数を作成します。たとえば、$matchisが(角かっこなしで)戻り、配列名に[noun]なる場合:。このトピックの詳細については、変数変数を参照してください。trim($matches[1],"[]")noun${noun}$noun

    • 2行目は、で使用可能なインデックス番号をランダムに選択し、$arrayこの位置にある要素を返します。

  • 3番目のパラメーターは入力文字列です。

于 2012-08-07T10:34:16.870 に答える
1

以下のコードが機能します。

$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()。この関数には、内部に$replaces2次元の深い配列が定義されており、各行は[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つは次のようになり、可能な置換が不足していることを示しています。

これはとても大きな家で、これは大きな家です。これも小さいです。

于 2012-08-07T10:50:55.553 に答える
1

これを行う別の良い(より簡単な)方法(私の解決策ではありません)

https://stackoverflow.com/a/15773754/2183699

foreachを使用して、置換する変数を確認し、それらを置換します

str_replace();
于 2014-01-08T16:37:54.180 に答える
0

preg_matchおよびstr_replace関数を使用して、この目標を達成できます。

  • 最初にpreg_match関数を使用して一致を検索し、次に結果から検索と置換の配列を作成します。
  • 前の配列をパラメーターとして渡して、str_replace関数を呼び出します。
于 2012-08-07T10:47:02.670 に答える
0

これは、上記のmmdemirbasの回答に対する私のマイナーアップデートです。これにより、関数の外部で変数を設定できます(つまり、前述のようにグローバルを使用します)。

$result    = preg_replace_callback(

                 // Matches parts to be replaced: '[adjective]', '[noun]'
                 '/(\[.*?\])/',

                 // Callback function. Use 'use()' or define arrays as 'global'
                 function($matches) use ($adjective, $noun) {

                     // Remove square brackets from the match
                     // then use it as variable name
                    $arrayname = trim($matches[1],"[]");
                    $array = $GLOBALS[$arrayname];

                     // Pick an item from the related array whichever.
                     return $array[array_rand($array)];
                 },

                 // Input string to search in.
                 $string
             );

print $result;
于 2012-08-11T15:02:04.453 に答える