递归数组爆炸

时间:2012-05-31 20:24:26

标签: php arrays recursion

我的字符串结构类似

(cat,dog,fish) && (drinks) && (milk,water)

我需要转换为像

这样的数组列表
cat drinks milk
cat drinks water
dog drinks milk
dog drinks water
fish drinks milk
fish drinks water

我想过用一个循环来完成它,它接受每个组并将它们插入到像

这样的数组中 第0遍: 用第一行填充数组

(cat,dog,fish) && (drinks) && (milk,water)
第一遍: 检测第一组并在删除源时将其拆分

cat && (drinks) && (milk,water) 
dog && (drinks) && (milk,water) 
fish && (drinks) && (milk,water)
第二遍 ....

然后每次循环这个行拆分它将它添加到最后并删除原始。

你有更好的主意吗?在PHP中?

对于那些想知道它是句子解析代码的一部分我正在写。

由于

2 个答案:

答案 0 :(得分:2)

使用普通的字符串解析来获得与其分组对应的3个数组。我想你可以用explode()

搞清楚

然后生成3个阵列的“笛卡尔积”

$iterators = array(
    new ArrayIterator(array('cat', 'dog', 'fish'))
  , new ArrayIterator(array('drinks'))
  , new ArrayIterator(array('milk', 'water'))
);
$citer = new CartesianProductIterator($iterators);
foreach ($citer as $combo) {
    printf("[%s]\n", join(',', $combo));
}

使用

class CartesianProductIterator implements Iterator {
    protected $iterators;

    function __construct(array $iters) {
        $this->iterators = $iters;
    }

    function rewind() {
        foreach ($this->iterators as $it) {
            $it->rewind();
        }
    }

    function current() {
        $values = array();
        foreach ($this->iterators as $it) {
            $values[] = $it->current();
        }
        return $values;
    }

    function key() {
        return null;
    }

    function next() {
        /*      
        loop them in reverse, but exclude first
        why? example, odometer: 55199
        you always check the rightmost digit first to see if incrementing it would roll it over and need to be "rewound" to 0, 
        which causes the digit to the left to increase as well, which may also cause it to roll over as well, and so on...
        looping in reverse operates from right column to the left.
        we dont rewind the first column because if the leftmost column is on its last element and needs to roll over
        then this iterator has reached its end, and so rewind() needs to be explicitly called 
        */
        for ($i = count($this->iterators) - 1; $i > 0; --$i) {
            $it = $this->iterators[$i];
            $it->next();
            if ($it->valid()) {
                // were done advancing because we found a column that didnt roll over
                return;
            } else {
                $it->rewind();
            }
        }

        //if execution reached here, then all of the columns have rolled over, so we must attempt to roll over the left most column
        $this->iterators[0]->next();
    }

    function valid() {
        return $this->iterators[0]->valid();
    }
}

答案 1 :(得分:1)

一旦我需要制作类似套装的每个组合。我有一个递归函数,在大数组上实际上是非常耗费资源的(9个部分,每个包含5个项目),但我可以尝试为你调整它:

$input=array(array("cat","dog","fish"),array("drinks"),array("milk","water"));
$output=array();
function combination($string,$level)
{
  global $output;
  global $input;
  if (isset($input[$level]))
  {
    $item=$input[$level];
    if (is_array($item))
    {
      foreach ($item as $i)     
        combination($string." ".$i,$level+1);
    }
    else
      combination($string." ".$item,$level+1);
  }
  else
    $output[]=$string;
}
combination("",0);
var_export($output);

然而,将您的字符串转换为输入数组是不同的问题,我不知道如何解决,所以我将继续为您服务。

相关问题