2012-05-06 94 views
4

我想循環遍歷一個二維數組並自動獲取列的組合的總和。PHP for for循環for循環。試圖對多個數組列進行求和以得到組合

假設我有一個名爲$ a的4列的排列:0,1,2,3,

$a=array(); 
$a[0][0]=1; 
$a[0][1]=3; 
$a[0][2]=5; 

$a[1][0]=10; 
$a[1][1]=2; 
$a[1][2]=5; 
$a[1][3]=7; 

$a[2][0]=9; 
$a[2][1]=8; 
$a[2][2]=9; 
$a[2][3]=8; 

$a[3][0]=9; 
$a[3][1]=8; 
$a[3][2]=9; 
$a[3][3]=8; 
$a[3][4]=1; 

,我試圖總結了所有喜歡和列(0組合, 0; 1,0; 2; 0.3; 0)等使用此代碼

for($i=0;$i<count($a[0]);$i++){ 
for($l=0;$l<count($a[1]);$l++){ 
for($s=0;$s<count($a[2]);$s++){ 
for($m=0;$m<count($a[3]);$m++){ 
echo $sum[]= $a[0][$i]+$a[1][$l]+$a[2][$s]+$a[3][$m]; 
echo $sum; 
    echo "<br>"; 
    } 
    } 
} 
} 

?> 

和代碼的工作,問題是,我手動做這些for循環,必須有某種方式在我可以通過某種方式簡化這個插入列數的計數?

我想是這樣

$numberofcolumns=4; 

for($n=0;$n<$numberofcolumns;$n++){ 
for($i=0;$i<count($a[$n]);$i++){ 
for($m=0;$m<count($a[$n+1]);$m++){ 
echo $sums[]= $a[$n][$i]+$a[$n+1][$m]; 
} 
} 
} 

,但不起作用,必須有某種方式來簡化for循環,這樣我就不必手動鍵入for循環每列

有人有線索嗎?

+0

你可能想看看'foreach'。 – Sietse

+0

預期產出應該如何?很多回聲? $作爲一個新的數組總和? –

+0

很多的回聲。他們都是列的組合 –

回答

1

您可以使用遞歸,或者只是直接嵌套循環這一點,但是當使用組合或置換,可能​​性的總數可能會爆炸併成爲一個龐大的數字,這會消耗大量的內存以至於無法運行代碼。使用迭代器是交換cpu效率以提高內存效率的好方法。這是我寫的一個迭代器。

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 ($a as $columnNumber => $values) { 
    $iterators[] = new ArrayIterator($values); 
} 
foreach (new CartesianProductIterator($iterators) as $combo) { 
    // combo has 1 value from each of the ArrayIterators we instantiated 
    printf("summing %s = %d\n", join('+', $combo), array_sum($combo)); 
} 

繼承人演示http://codepad.org/UasdgvWf

+0

感謝這工作!出於好奇,如何用循環來解決這個問題?順便說一句,謝謝你理解我想要做什麼,一直在努力。 –

+0

好吧,很多人會爲此寫一個遞歸函數,而且這不會太困難。任何遞歸算法都可以重寫爲迭代算法,並且您可以使用堆棧的概念跟蹤所有變量的狀態,就像編譯器對任何編程語言所做的一樣。有幾次我完成了它,這有點讓人爲我彎腰,我現在並不覺得它現在。 – goat

1

您可以使用RecursiveIteratorIterator

嘗試

$a = array(); 
$a [0] [0] = 1; 
$a [0] [1] = 3; 
$a [0] [2] = 5; 

$a [1] [0] = 10; 
$a [1] [1] = 2; 
$a [1] [2] = 5; 
$a [1] [3] = 7; 

$a [2] [0] = 9; 
$a [2] [1] = 8; 
$a [2] [2] = 9; 
$a [2] [3] = 8; 

$a [3] [0] = 9; 
$a [3] [1] = 8; 
$a [3] [2] = 9; 
$a [3] [3] = 8; 
$a [3] [4] = 1; 

$sum = 0; 
$array = new RecursiveIteratorIterator (new RecursiveArrayIterator ($a)); 
foreach ($array as $key => $value) { 
     $sum += $value; 
} 
echo $sum; 

輸出

102 

使用$array = new RecursiveIteratorIterator (new RecursiveArrayIterator ($a[1]));得到各部分的總和......

+0

謝謝,這適用於第一個組合,所以我只是循環它來獲得所有的組合? –

+0

你是什麼意思的所有組合? – Baba

+0

像第一行是1 + 10 + 9 + 9,那麼我總結1 + 10 + 9 + 8([0] [0] [1] [0] [2] [0] [3] [1] ),然後我總結1 + 10 + 9 + 9([0] [0] [1] [0] [2] [0] [3] [3]),然後我總結所有可能的組合列基本上。這就是那些for循環做 –

0

如果我正確認識你,這個功能應該可以做到這一點:

<?php 
function recursive_sum($arr) { 

    $sum = 0; 

    foreach($arr as $value) { 
     if(is_array($value)) { 
      $sum += recursive_sum($value); 
     } 
     else { 
      $sum += $value; 
     } 
    } 

    return $sum; 
} 
?> 

只需撥打recursive_sum($a)把所有的值的總和數組中,像這樣:

<?php 
    echo recursive_sum($a); 
?>  
+0

我不想總結所有的列,我試圖總結組合總和由第一列,第二,第三和第四列的數字組成。這就是for循環所做的事情,但我試圖讓它自動化,無論我有多少列,我仍然可以獲得所有不同組合的總和 –

+0

對不起,但我遇到了一些麻煩了解你在找什麼。我試着運行你的示例代碼(你說的那個代碼),但是這給了我一些垃圾輸出和一個致命的錯誤(PHP 5.3.8)。你可以編輯你的文章來添加你正在尋找的輸出的幾個例子嗎? – Daan

+0

由於某種原因,它不會讓我編輯我的帖子,一直說我的代碼沒有正確的間隔。如果你以結尾的位置,它將爲您提供一系列數字輸出,如array29,array 28等,它們只是列的行的總和,我想要做的是自動化的for循環,無論我有多少列(目前4),代碼將總結所有的組合 –

0
<? //PHP 5.4+ 
$a=[]; 
$a[0][0]=1; 
$a[0][1]=3; 
$a[0][2]=5; 

$a[1][0]=10; 
$a[1][1]=2; 
$a[1][2]=5; 
$a[1][3]=7; 

$a[2][0]=9; 
$a[2][1]=8; 
$a[2][2]=9; 
$a[2][3]=8; 

$a[3][0]=9; 
$a[3][1]=8; 
$a[3][2]=9; 
$a[3][3]=8; 
$a[3][4]=1; 

//This is downright evil, but it works. 
eval(\array_reduce(
    \array_reverse(\array_keys($a)), 
    static function($eval, $key){ 
    return "foreach(\$a[$key]as\$i$key)$eval+\$i$key"; 
    }, 
    '{echo$sum[]=0') . ';echo"$sum<br/>";}'); 
?>