Как сохранить и сбросить указатель массива PHP? - PullRequest
4 голосов
/ 30 ноября 2008

У меня есть ассоциативный массив, т.е.

$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 также перебирает массив $ primes,

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 (), чтобы он не имел этого побочного эффекта. Есть ли способ сделать это?

Ответы [ 5 ]

4 голосов
/ 30 ноября 2008

Не полагайтесь на указатели массива. Вместо этого используйте итераторы.

Вы можете заменить свой внешний код на:

foreach ($primes as $p) {
  if ($p > 10000 && IsPrime(doSomeCalculationsOn($p))) {
    return $p;
  }
}
4 голосов
/ 30 ноября 2008

Вы можете «сохранить» состояние массива:

$state = key($array);

И "восстановить" (не уверен, что есть лучший метод):

reset($array);

while(key($array) != $state)
    next($array);
0 голосов
/ 30 ноября 2008

используйте цикл 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;
}

таким образом внутренний указатель массива не будет использоваться в методе.

0 голосов
/ 30 ноября 2008

Как насчет создания еще одного массива int -> int, где индекс - это бегущее число от 0 до n , а значение - индекс ассоциативного массива? Итак, вы бы имели:

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

и вместо прямой ссылки на $prime вы бы использовали $prime[$pointer[$i]] или что-то подобное?

0 голосов
/ 30 ноября 2008

Если скорость не является проблемой, и вы не расширяете пределы памяти php, самое быстрое решение - просто скопировать массив простых чисел и повторить 2 разных.

$awesomePrimes=$primes;

Затем измените глобальные переменные и foreach в своей функции на $awesomePrimes

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...