2012-05-07 60 views
-1

我有一組數組,其中包含不同組合的字符串/組(在本例中爲大寫和小寫)。我試圖循環這個數組 - 使用PHP - 並生成從原始字符串可以組成的所有可能組合連接的新字符串。PHP:連接數組中的可能組合

數組是這樣的:

Array 
(
    [0] => Array 
     (
      [0] => ALFA 
      [1] => alfa 
     ) 
    [1] => Array 
     (
      [0] => BETA 
      [1] => beta 
     ) 
    [2] => Array 
     (
      [0] => DELTA 
      [1] => delta 
     ) 
) 

的出來把我想有應該是這樣的:

ALFA 
ALFA BETA 
ALFA beta 
ALFA DELTA 
ALFA delta 
ALFA BETA DELTA 
ALFA BETA delta 
ALFA beta beta 
ALFA DELTA BETA 
ALFA DELTA beta 
ALFA delta BETA 
ALFA delta beta 
alfa 
alfa BETA 
alfa beta 
alfa DELTA 
alfa delta 
alfa BETA DELTA 
alfa BETA delta 
alfa beta beta 
alfa DELTA BETA 
alfa DELTA beta 
alfa delta BETA 
alfa delta beta 
BETA 
BETA ALFA 
BETA alfa 
BETA DELTA 
BETA delta 
BETA ALFA delta 
BETA ALFA DELTA 
BETA alfa delta 
BETA alfa DELTA 
BETA DELTA alfa 
BETA DELTA ALFA 
BETA delta alfa 
BETA delta ALFA 
beta 
beta ALFA 
... 
... 

我花了一整天時間來弄清楚這一點,但卡住了。任何輸入或幫助非常感謝,謝謝!

+3

這是一個非常簡單的問題,解決的辦法是直接的,你可以特別指定其使用,但讓我問你*爲什麼*你想做這個?幾乎可以肯定的是,以這種非常低性能和高內存的方式來完成你想要完成的任務的更好方式。 –

+2

需要多長時間輸入預期的輸出,並手動完成想要腳本自動執行的操作? –

+0

@Mahmoud:我試圖完成的是一個腳本,它需要1-4個輸入字符串並用這些單詞的所有可能組合生成一個單詞列表。每個輸入字符串也將採用不同的格式,例如大寫字母,小寫字母,高位字母,高位字母等。 –

回答

0

您可以存儲只包含這些字符串的小寫版本的數組,然後動態地大寫它(strtoupper執行作業)。

具有嵌套 for循環

然後或者使用遞歸你去通過該陣列的每個元素和echo需要(只是跳過你是相同的元件在迭代(或遞歸)的兩個層,其中例)的各種組合

0

同意@Mahmoud Al-Qudsi,這似乎是一個奇怪的問題,並且如果數組大於平凡的大小,可以很容易地將你的服務器掐死。你意識到我們在這裏討論階乘因子 - 如果你的數組有10個元素,那麼在一個例子中所有10個字符串的排列數就是10!這是3.5百萬增加大小寫版本,添加與9,8等元素的字符串的組合,並且我們談論非常長的計算。在10個元素陣列之後,每增加一個,計算的數量乘以至少10,即35百萬與11,350百萬,其中12 ...你得到漂移。

0

使用

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

如下

$iterators = array(); 
foreach ($arr as $possibleChoicesForOneSlotInACombo) { 
    //we add null as a way indicate "no value" as a choice for this slot 
    $possibleChoicesForOneSlotInACombo[] = null; 
    $iterators[] = new ArrayIterator($possibleChoicesForOneSlotInACombo); 
} 

foreach (new CartesianProductIterator($iterators) as $combo) { 
    //filter out the possible nulls that might exist in this combo 
    $strings = array_filter($combo, 'is_string'); 

    // make sure something exists, maybe they were all null 
    if ($strings) { 
     echo join(' ', $strings), "\n"; 
    } 
}