对于我正在处理的项目,我有一个带占位符的基URI,并且我希望使用PHP从每个占位符的可能值数组中生成所有可能的组合。
更具体地说:
<?php
$uri = "foo/bar?foo=%foo%&bar=%bar%";
$placeholders = array(
'%foo%' => array('a', 'b'),
'%bar%' => array('c', 'd'),
// ...
);
我想最终得到以下数组:
array(4) {
[0]=>
string(23) "foo/bar?foo=a&bar=c"
[1]=>
string(23) "foo/bar?foo=a&bar=d"
[2]=>
string(19) "foo/bar?foo=b&bar=c"
[3]=>
string(19) "foo/bar?foo=b&bar=d"
}
更不用说我应该能够添加更多的占位符来生成更多的计算uris,当然,所以解决方案应该递归地工作。
这些天我可能会过度疲惫,但我很难实现这一点,而且我确信有一种简单的方法,甚至可能还有内置的PHP函数......
提示?任何帮助非常感谢。
答案 0 :(得分:4)
<?php
function rec($values,$keys,$index,$str,&$result)
{
if($index<count($values))
foreach($values[$index] as $val)
rec($values,$keys,$index+1,$str.substr($keys[$index],1,strlen($keys[$index])-2)."=".$val."&",$result);
else
$result[count($result)] = $str;
}
// Now for test
$placeholders = array(
'%foo%' => array('a', 'b'),
'%bar%' => array('c', 'd' , 'h'),
);
$xvalues = array_values($placeholders) ;
$xkeys = array_keys($placeholders) ;
$result = array();
rec($xvalues,$xkeys,0,"",$result); // calling the recursive function
print_r($result);
// the result will be:
Array (
[0] => foo=a&bar=c&
[1] => foo=a&bar=d&
[2] => foo=a&bar=h&
[3] => foo=b&bar=c&
[4] => foo=b&bar=d&
[5] => foo=b&bar=h&
)
?>
它处理无限数量的占位符和&amp;无限数量的值
答案 1 :(得分:3)
$uri= "foo/bar?foo=%foo%&bar=%bar%&baz=%baz%";
$placeholders = array(
'%foo%' => array('a', 'b'),
'%bar%' => array('c', 'd', 'e'),
'%baz%' => array('f', 'g')
);
//adds a level of depth in the combinations for each new array of values
function expandCombinations($combinations, $values)
{
$results = array();
$i=0;
//combine each existing combination with all the new values
foreach($combinations as $combination) {
foreach($values as $value) {
$results[$i] = is_array($combination) ? $combination : array($combination);
$results[$i][] = $value;
$i++;
}
}
return $results;
}
//generate the combinations
$patterns = array();
foreach($placeholders as $pattern => $values)
{
$patterns[] = $pattern;
$combinations = isset($combinations) ? expandCombinations($combinations, $values) : $values;
}
//generate the uris for each combination
foreach($combinations as $combination)
{
echo str_replace($patterns, $combination, $uri),"\n";
}
这里的想法是在数组中列出替换的所有可能组合。函数expandCombinations只是在每个新模式的组合中添加一个深度级别来替换没有递归(我们知道PHP如何喜欢递归)。这应该允许替换相当数量的模式而不会在疯狂的深度进行递归。
答案 2 :(得分:2)
递归解决方案:
function enumerate($uri, $placeholders){
$insts = array();
if (!empty($placeholders)){
$key = array_keys($placeholders)[0];
$values = array_pop($placeholders);
foreach($values => $value){
$inst = str_replace($uri, $key, $value);
$insts = array_merge($insts, (array)enumerate($inst, $placeholders));
}
return $insts;
} else {
return $uri;
}
}
对函数的每次调用都会弹出数组中的一个占位符,并循环遍历其潜在值,枚举每个占位符的所有剩余占位符值。复杂度为O(k ^ n),其中k是每个占位符的平均替换次数,n是占位符的数量。
我的PHP有点生疏;如果我的语法错误,请告诉我。
答案 3 :(得分:1)
foreach($placeholders['%foo%'] as $foo){
foreach($placeholders['%bar%'] as $bar){
$container[] = str_replace(array('%foo%','%bar%'),array($foo,$bar),$uri);
}
}
答案 4 :(得分:0)
这项工作,但它不是那么优雅,因为需要摆脱占位符数组键:
<?php
/*
* borrowed from http://www.theserverpages.com/php/manual/en/ref.array.php
* author: skopek at mediatac dot com
*/
function array_cartesian_product($arrays) {
//returned array...
$cartesic = array();
//calculate expected size of cartesian array...
$size = sizeof($arrays) > 0 ? 1 : 0;
foreach ($arrays as $array) {
$size *= sizeof($array);
}
for ($i = 0; $i < $size; $i++) {
$cartesic[$i] = array();
for ($j = 0; $j < sizeof($arrays); $j++) {
$current = current($arrays[$j]);
array_push($cartesic[$i], $current);
}
//set cursor on next element in the arrays, beginning with the last array
for ($j = sizeof($arrays) - 1; $j >= 0; $j--) {
//if next returns true, then break
if (next($arrays[$j])) {
break;
} else { //if next returns false, then reset and go on with previuos array...
reset($arrays[$j]);
}
}
}
return $cartesic;
}
$uri = "foo/bar?foo=%foo%&bar=%bar%";
$placeholders = array(
0 => array('a', 'b'), // '%foo%'
1 => array('c', 'd'), // '%bar%'
);
//example
header("Content-type: text/plain");
$prod = array_cartesian_product($placeholders);
$result = array();
foreach ($prod as $vals) {
$temp = str_replace('%foo%', $vals[0], $uri);
$temp = str_replace('%bar%', $vals[1], $temp);
array_push($result, $temp);
}
print_r($result);
?>