2012-05-31 2 views
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 

Я думал, что делать это с петлей, которая принимает каждую группу и вкладыши их в массив, как

0th проход: заполнить массив с первой строкой

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

первый проход: обнаружить первую группу и разделить ее, удаляя источник

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

второй проход ....

затем цикл это каждый раз, когда принимают линию разделить его добавить его конец и удалить оригинал.

У вас есть идея? и в PHP?

Для тех, кто задается вопросом. Это часть кода анализа предложений, который я пишу.

Благодаря

+1

звучит как у вас есть правильная идея, так что идти напишите код :-) –

+2

но .. но .. рыба не пьет молоко :( – Nanne

+0

да, но мой код не будет рекурсивным, это будет цикл повторения, пока не будет ничего, что нужно обработать :-) либо научить рыбу пить молоко, либо изменить код. – Ekim

ответ

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

Однако преобразование строки в входной массив отличается проблема , который я не уверен, как решить, поэтому я буду поддерживать это до вас.

2

использовать обычный синтаксический анализ строк, чтобы получить 3 массива, которые соответствуют их группировкам. Я думаю, что вы можете понять это с взорваться()

Затем генерировать «декартово произведение» из 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(); 
    } 
} 
+0

Спасибо за решение, раньше я не знал об ArrayIterator. Я закончил использовать другое решение. Но ваше решение очень элегантно, я не мог принять оба :-( – Ekim

Смежные вопросы