我正在尝试用其他网址替换网址中的$1, $2, $3
个变量。
您可以复制粘贴下面的示例并查看我的解决方案。
但我觉得有一种更优雅的方式,使用数组映射类型函数或更好的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);
}
答案 0 :(得分: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
进行一些调整。例如,如果回调通过数组而不是单独的参数获取元素可能会更好。当任何数组用完元素时,可能应该有选项标志停止,而不是填充空值。
以下是我提出的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 :(得分: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);
}
答案 2 :(得分: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)));
}
?>
您也可以使用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));
}
?>
答案 3 :(得分: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
也许有理由保持数组键=&gt;完成替换的价值?