2008-11-30 59 views
4

我有一個關聯數組,即如何存儲和重置PHP數組指針?

$primes = array(
    2=>2, 
    3=>3, 
    5=>5, 
    7=>7, 
    11=>11, 
    13=>13, 
    17=>17, 
    // ...etc 
); 

然後我做

// seek to first prime greater than 10000 
reset($primes); 
while(next($primes) < 10000) {} 
prev($primes); 

// iterate until target found 
while($p = next($primes)) { 
     $res = doSomeCalculationsOn($p); 

     if(IsPrime($res)) 
      return $p; 
} 

的問題是,IsPrime也遍歷$素數數組,

function IsPrime($num) { 
    global $primesto, $primes, $lastprime; 

    if ($primesto >= $num) 
     // using the assoc array lets me do this as a lookup 
     return isset($primes[$num]); 

    $root = (int) sqrt($num); 
    if ($primesto < $root) 
     CalcPrimesTo($root); 

    foreach($primes as $p) {  // <- Danger, Will Robinson! 
     if($num % $p == 0) 
      return false; 

     if ($p >= $root) 
      break; 
    } 

    return true; 
} 

它象垃圾一樣清除數組我正在迭代的指針。

我想能夠保存和恢復數組的內部指針在IsPrime()函數,所以它沒有這種副作用。有沒有辦法做到這一點?

+0

+1爲危險,威爾羅賓遜! – n0nag0n 2012-08-22 20:39:52

回答

4

不要依賴數組指針。改用迭代器。

您可以取代你的外碼:

foreach ($primes as $p) { 
    if ($p > 10000 && IsPrime(doSomeCalculationsOn($p))) { 
    return $p; 
    } 
} 
4

可以「拯救」陣列的狀態:

$state = key($array); 

和「恢復」(不知道是否有一個更好的方法):

reset($array); 

while(key($array) != $state) 
    next($array); 
+0

嗯...正確的效果,但這是O(n)在數組的大小,這使得我的算法O(n^2)這是不可接受的。 我想知道如何延長重置($ arr,$ key = 0)? (重置開始或指定的鍵值?) – 2008-11-30 20:14:41

+0

這個答案可能不是「最佳實踐」,但它是這個問題的正確答案,...... imo。 – aurora 2014-03-04 14:54:28

0

如果速度不是問題,你不推動php內存限制最快的解決方案只是複製你的素數組並迭代2個不同的數組。

$awesomePrimes=$primes; 

然後改變全局和foreach在你的函數$awesomePrimes

+0

對於包含2百萬項的數組,它使用額外的68MB內存 - 不是世界的盡頭,但看起來很浪費。 – 2008-11-30 20:23:18

0

如何做的int -> int,其中該指數是從0到ñ和值運行多一個數組的索引關聯數組?所以,你會:

$pointer = array(
    0 => 2, 
    1 => 3, 
    2 => 5, 
    // ... 
); 

,而是直接引用$prime你會用$prime[$pointer[$i]],或類似的東西嗎?

0

對你的一個迭代使用「for」循環。例如,在您的IsPrime方法中使用此循環:

$primesLength = count($primes); // this is to avoid calling of count() so many times. 
for ($counter=0 ; $counter < $primesLength ; $counter++) { 
    $p = $primesLength[$counter]; 
    if($num % $p == 0) 
      return false; 

    if ($p >= $root) 
      break; 
} 

這樣,內部數組指針將不會在方法中使用。