【问题标题】:PHP Arrays and Recursive IterationsPHP 数组和递归迭代
【发布时间】:2013-07-27 20:37:26
【问题描述】:

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

这里是场景:

我有一个类似这样的短语:

[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 代码来获取输入的短语,并返回所有可能的句子。

【问题讨论】:

  • 有限状态机解析短语并生成所有句子?
  • 为了我的目的,我想我们可以限制每个 [] 组 10 个可能的项目,并且句子中总共有 10 个“片段”(每个片段可以是一个奇异值,或一个 []团体)。这能回答吗?
  • 我认为,每组可以做任意数量的项目
  • 您要做的是找到可能输入的笛卡尔积,然后使用简单的foreach 生成您想要的输出是微不足道的。有几种很好的方法可以做到这一点(包括我自己的答案):stackoverflow.com/questions/6311779/…。如果您需要有关如何执行此操作的更多指导,我可以扩展为答案。

标签: php arrays recursion


【解决方案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) 太旧了。

【讨论】:

  • 谢谢!这正是我想要的(尤其是 generator() 函数)!
  • @OneNerd 从睡梦中醒来后,我意识到,如何改进功能。看看:我摆脱了 is_null 检查。
【解决方案2】:

首先,您必须拆分输入字符串并将其重写为数组。这将有这样的输出:(我会使用 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;
        }
    }
}

【讨论】:

    【解决方案3】:
    $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

    【讨论】:

      【解决方案4】:

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

      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);
      

      【讨论】:

      • 任何方式(使用您的代码)来解释字符串中或多或少的 3 个 [] 括号工作组?
      猜你喜欢
      • 2020-03-21
      • 2017-02-02
      • 2013-11-11
      • 2014-05-13
      • 2011-11-14
      • 2014-10-18
      • 2018-09-20
      • 2013-12-01
      • 2013-06-14
      相关资源
      最近更新 更多