0

我的字符串结构像

(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 中?

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

谢谢

4

2 回答 2

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();
    }
}
于 2012-05-31T20:58:48.517 回答
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);

然而,将你的字符串转换为输入数组是不同的问题,我不知道如何解决,所以我会一直由你决定。

于 2012-05-31T20:57:20.437 回答