2

我有一个场景,我认为需要某种递归迭代,但我不确定,而且不是递归编码专家,我正在画一个空白。

这是场景:

我有这样一句话:

[He|She] would [like|love|hate] to [Play Golf|Play Tennis|Play Baseball] Today.

我希望 PHP 解析该短语([] 括号内的每个部分表示该单词或短语的可能变体,每个可能性由 | 管道分隔),并生成所有变体,例如,上面将返回:

He would like to Play Golf Today. 
He would like to Play Tennis Today.
He would like to Play Baseball Today.
He would love to Play Golf Today.
He would love to Play Tennis Today.
He would love to Play Baseball Today.
He would hate to Play Golf Today.
He would hate to Play Tennis Today.
He would hate to Play Baseball Today.
She would like to Play Golf Today.
She would like to Play Tennis Today.
She would like to Play Baseball Today.
She would love to Play Golf Today.
She would love to Play Tennis Today.
She would love to Play Baseball Today.
She would hate to Play Golf Today.
She would hate to Play Tennis Today.
She would hate to Play Baseball Today.

我试图弄清楚如何编写 PHP 代码来获取输入的短语,并返回所有可能的句子。

4

4 回答 4

1

这是一个递归解决方案:

<?php
function generator($input, &$result)
{
    $matches = array();
    if (preg_match('/\[(.*?)\]/', $input, $matches))
    {
        $words = explode('|', $matches[1]);
        $n = count($words);
        for ($i = 0; $i < $n; ++$i)
        {
            $input1 = str_replace($matches[0], $words[$i], $input);
            generator($input1, $result);
        }
    }
    else
    {
        $result[] = $input;
    }
}

$input = '[He|She] would [like|love|hate]';
$result = array();
generator($input, $result);
var_dump($result);

打印 2*3 = 6 种组合:

array(6) {
  [0]=>
  string(13) "He would like"
  [1]=>
  string(13) "He would love"
  [2]=>
  string(13) "He would hate"
  [3]=>
  string(14) "She would like"
  [4]=>
  string(14) "She would love"
  [5]=>
  string(14) "She would hate"
}

我想使用 yeild,但我的 php 版本(5.4.7)太旧了。

于 2013-07-27T21:51:37.120 回答
0

首先,您必须拆分输入字符串并将其重写为数组。这将有这样的输出:(我会使用 strpos、regexp 和/或explode 来拆分所有部分)

Array(
    [0]=> Array(
        [0] => 'He',
        [1] => 'She'),
    [1]=> Array(
        [0] => ' would '),
    [2]=> Array(
        [0] => 'like',
        [1] => 'love',
        [2] => 'hate'),
...
)

在您必须遍历数组并构建所有组合并将它们存储到字符串中之后。这看起来像这样

//this is for tracking the progress
for($x = 0; $x < count($array_parts); $x++)
{
    //starting all at the first option
    $array_tracker[$x] = 0;
}

while(true)
{
    //build selected possibility
    $ouput_string = "";
    for($x = 0; $x < count($array_parts); $x++)
    {
        $ouput_string .= $array_parts[$x][$array_tracker[$x]];
    }
    $output_strings[] = $output_string;

    //navigate to next possibility
    for($x = count($array_parts) - 1; $x >= 0; $x--)
    {
        $array_tracker[$x]++;
        if($array_tracker[$x] == count($array_parts[$x))
        {
            $array_tracker[$x] = 0;
        }
        else
        {
            break;
        }
        if($x == 0)
        {
            //all option are done, than end this 'endless' loop
            break 2;
        }
    }
}
于 2013-07-27T22:15:30.970 回答
0
$string = '[He|She] would [like|love|hate] to [Play Golf|Play Tennis|Play Baseball] Today.';
$parts = explode("]", $string);
$newparts = array();
$loops = array();
foreach($parts as $part){
 if(strpos($part, '[') !== false){
    $part = preg_replace("#([^\[]+)?\[#", "", $part);
    $loops[] = explode("|", $part);
 }
}
//matching other words

$words = preg_replace("#\[(.*?)\]#", '', $string);
$words = preg_replace("#\s+#", '|', trim($words));
$words = explode("|", $words);

foreach($loops as $key => &$val){

    foreach($val as &$word){
      $word = $word.' '.$words[$key];
    }
}
$data =array();

$eval = '
 $data =array();
 ';
$eval_blocks = '';
$eval_foreach = '';
$eval_data = '
$data[] = ';
$looplength = count($loops);
for($i=0; $i<$looplength; $i++){
 $eval_foreach.= '
 foreach($loops['.$i.'] as $val'.($i+1).'){
 ';
 if( ($i+1) == $looplength ){
  $eval_data .= ' $val'.($i+1).';';
 }else{
  $eval_data .= ' $val'.($i+1).' ." ".';
 }
 $eval_blocks .= '
 }
 ';
}
$eval = $eval. $eval_foreach . $eval_data . $eval_blocks;
echo "<hr>";
print_r($words);
print_r($loops);
print_r($data);

输出:

Array
(
    [0] => would
    [1] => to
    [2] => Today.
)
Array
(
    [0] => Array
        (
            [0] => He would
            [1] => She would
        )

    [1] => Array
        (
            [0] => like to
            [1] => love to
            [2] => hate to
        )

    [2] => Array
        (
            [0] => Play Golf Today.
            [1] => Play Tennis Today.
            [2] => Play Baseball Today.
        )

)
Array
(
    [0] => He would like to Play Golf Today.
    [1] => He would like to Play Tennis Today.
    [2] => He would like to Play Baseball Today.
    [3] => He would love to Play Golf Today.
    [4] => He would love to Play Tennis Today.
    [5] => He would love to Play Baseball Today.
    [6] => He would hate to Play Golf Today.
    [7] => He would hate to Play Tennis Today.
    [8] => He would hate to Play Baseball Today.
    [9] => She would like to Play Golf Today.
    [10] => She would like to Play Tennis Today.
    [11] => She would like to Play Baseball Today.
    [12] => She would love to Play Golf Today.
    [13] => She would love to Play Tennis Today.
    [14] => She would love to Play Baseball Today.
    [15] => She would hate to Play Golf Today.
    [16] => She would hate to Play Tennis Today.
    [17] => She would hate to Play Baseball Today.
)

更新:动态创建的循环。

演示:http ://codepad.org/eeQd9S0r

于 2013-07-27T22:40:42.550 回答
0

用于生成组合的递归函数:

function combix($items, $combos=array()){
    $res = array();
    $next = array_shift($items);
    if (is_array($next)){
        if (empty($combos)){
            return combix($items, $next);
        }
        foreach ($combos as $key => $value){
            foreach ($next as $key2 => $value2){
                if (is_array($value)){
                    $res[] = array_merge($value, array($value2));
                } else {
                    $res[] = array($value, $value2);
                }
            }
        }
        return combix($items, $res);
    } else {
        return $combos;
    }
}

文本处理:

$str = '[He|She] would [like|love|hate] to [Play Golf|Play Tennis|Play Baseball] Today.';
$pattern = '#\[([\w\s|]+)]#';
if (preg_match_all($pattern, $str, $matches)){
    $template = preg_replace($pattern, '%s', $str);
    $mix = array();
    foreach ($matches[1] as $key => $value){
        $mix[] = explode('|', $value);
    }
    $res = combix($mix);
    $out = array();
    foreach ($res as $key => $value){
        array_unshift($value, $template);
        $out[] = call_user_func_array('sprintf', $value);
    }
} else {
    $out = array($str);
}
print_r($out);
于 2013-07-28T03:01:54.017 回答