1

$1, $2, $3URL の変数を別の URLに置き換えようとしています。以下の例をコピーして貼り付けて、私の解決策を確認してください。

しかし、配列マッピング型関数またはより良い preg_replace 型のものを使用した、よりエレガントな方法があるように感じます。正しい方向へのキックが必要なだけです。助けてもらえますか?

    <?php
    /**
    *  Key = The DESIRED string
    *  Value = The ORIGINAL value
    *
    * Desired Result: project/EXAMPLE/something/OTHER
    */
    $data = array(
        'project/$1/details/$2' => 'newby/EXAMPLE/something/OTHER'
    );

    foreach($data as $desiredString => $findMe)
    {
        /**
        * Turn these URI's into arrays
        */
        $desiredString = explode('/', $desiredString);
        $findMe = explode('/', $findMe);

        /**
        * Store the array position of the match
        */
        $positions = array();
        foreach($desiredString as $key => $value) {
            /**
            * Look for $1, $2, $3, etc..
            */
            if (preg_match('#(\$\d)#', $value)) {
                $positions[$key] = $value;
            }
        }

        /**
        * Loop through the positions
        */
        foreach($positions as $key => $value){
            $desiredString[$key] = $findMe[$key];
        }

        /**
        * The final result
        */
        echo implode('/', $desiredString);
    }
4

4 に答える 4

2

なぜ $2,$4 ではなく $1,$2 であ​​るべきなのですか? 配列を変更できれば、3 行または 4 行のコードで解決できます。

$data = array(
    'project/$2/details/$4' => 'newby/EXAMPLE/something/OTHER'
);

foreach($data as $desiredString => $findMe)
{
    $regexp = "#(".implode(')/(',explode('/',$findMe)).")#i";
    echo preg_replace($regexp,$desiredString,$findMe);
}
于 2012-06-26T06:07:40.827 に答える
2

場合によっては、運が悪く、問題を直接解決するために必要な機能がそこにないことがあります。これは、ライブラリとビルトインの数に関係なく、すべての言語で発生します。

コードを書く必要があります。また、特定の問題を解決する必要があります。最終的には、最初から理想的な関数が与えられているかのように、問題に対する解決策がクリーンであることを望んでいます。したがって、どのようなコードを書く場合でも、ほとんどのコードを邪魔にならないようにする必要があります。これはおそらく、ほとんどのコードを別の関数またはクラスに配置する必要があることを意味します。しかし、すべての関数とクラスを再利用できるようにする必要があるため、単に任意のコードを放り投げる必要はありません。

次に、私のアプローチは、ソリューションから有用な一般的なパターンを抽出し、それを関数として記述し、その関数を使用して元のソリューションを書き直すことです (これにより単純化されます)。その一般的なパターンを見つけるために、問題を大きくして、より多くの状況に適用できるようにしました。

私は関数を作ってしまいましたarray array_multi_walk(callback $callback [, array $array1 [, array $array2 ... ]])。この関数は、各配列を同時に走査$callbackし、保持する要素を選択するために使用します。

これは、この関数を使用したソリューションのように見えます。

$chooser = function($a, $b) {
  return strlen($a) >= 2 && $a[0] == '$' && ctype_digit($a[1])
    ? $b : $a;
};

$data = array(
  'project/$1/details/$2' => 'newby/EXAMPLE/something/OTHER'
);

$explodeSlashes = function($a) { return explode('/', $a); };
$find = array_map($explodeSlashes, array_keys($data));
$replace = array_map($explodeSlashes, array_values($data));

$solution = array_multi_walk(
    function($f, $r) use ($chooser) {
        return array_multi_walk($chooser, $f, $r);
    },
    $find, $replace);

また、必要に応じて、array_multi_walk他の問題にも使用できます。たとえば、これはすべての要素を合計します。

$sum = function() {
  return array_sum(func_get_args());
};

var_dump(array_multi_walk($sum, array(1,2,3), array(1,2,3), array(10)));
// prints the array (12, 4, 6)

にいくつかの調整を加えたいと思うかもしれませんarray_multi_walk。たとえば、コールバックが要素を個別の引数ではなく、配列で取得する方がよい場合があります。null を埋める代わりに、配列の要素がなくなったときに停止するオプション フラグが必要かもしれません。

array_multi_walkこれが私が思いついた実装です。

function array_multi_walk($callback)
{
  $arrays = array_slice(func_get_args(), 1);
  $numArrays = count($arrays);
  if (count($arrays) == 0) return array();
  $result = array();
  for ($i = 0; ; ++$i) {
    $elementsAti = array();
    $allNull = true;
    for ($j = 0; $j < $numArrays; ++$j) {
      $element = array_key_exists($i, $arrays[$j]) ? $arrays[$j][$i] : null;
      $elementsAti[] = $element;
      $allNull = $allNull && $element === null;
    }
    if ($allNull) break;

    $result[] = call_user_func_array($callback, $elementsAti);
  }
  return $result;
}

そのため、1 日の終わりにコードを作成する必要がありましたが、元の問題に対する解決策が巧妙であるだけでなく、後で役立つ再利用可能な一般的なコードも得られました。

于 2012-06-26T05:41:01.923 に答える
1

読みやすくするためにコメントを削除して、コードを短縮しました。私が使用array_mapしているのは、マッピング関数が返す値を決定することです。

<?php

function replaceDollarSigns($desired, $replace)
{
    return preg_match('#(\$\d)#', $desired) ? $replace : $desired;
}

$data = array(
    'project/$1/details/$2' => 'newby/EXAMPLE/something/OTHER',
);

foreach($data as $desiredString => $findMe)
{
    $desiredString = explode('/', $desiredString);
    $findMe = explode('/', $findMe);
    var_dump(implode('/', array_map('replaceDollarSigns', $desiredString, $findMe)));
}
?>

実例: http: //ideone.com/qVLmn

を使用して関数を省略することもできますcreate_function

<?php

$data = array(
    'project/$1/details/$2' => 'newby/EXAMPLE/something/OTHER',
);

foreach($data as $desiredString => $findMe)
{
    $desiredString = explode('/', $desiredString);
    $findMe = explode('/', $findMe);
    $result = array_map(
        create_function(
            '$desired, $replace',
            'return preg_match(\'#(\$\d)#\', $desired) ? $replace : $desired;'
        ),
        $desiredString,
        $findMe);
    var_dump(implode('/', $result));
}
?>

実例: http: //ideone.com/OC0Ak

于 2012-06-26T05:57:13.050 に答える
0

preg_replaceで配列パターン/置換を使用しないのはなぜですか? このようなもの:

<?php
/**
*  Key = The DESIRED string
*  Value = The ORIGINAL value
*
* Desired Result: project/EXAMPLE/something/OTHER
*/
$data = array(
    'project/$1/details/$2' => 'newby/EXAMPLE/details/OTHER'
);
$string = 'project/$1/details/$2';

$pattern[0] = '/\$1/';
$pattern[1] = '/\$2/';
$replacement[0] = 'EXAMPLE';
$replacement[1] = 'OTHER';
$result = preg_replace($pattern, $replacement, $string);

echo $result;

あなたが探しているものよりもはるかに簡単だと思います。ここで動作することがわかります: http://codepad.org/rCslRmgs

おそらく、置換を実行するために配列キー => 値を保持する何らかの理由があるのでしょうか?

于 2012-06-26T18:08:49.713 に答える