Как сохранить и сбросить указатель массива 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 также перебирает массив $ 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 (), чтобы он не имел этого побочного эффекта. Есть какой-либо способ сделать это?

+1 за опасность, Уилл Робинсон!

n0nag0n 23.08.2012 00:39
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
4
1
7 720
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

$state = key($array);

И «восстановить» (не уверен, есть ли способ лучше):

reset($array);

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

Эм ... правильный эффект, но это O (n) в размере массива, что делает мой алгоритм O (n ^ 2) неприемлемым. Интересно, насколько сложно будет продлить сброс ($ arr, $ key = 0)? (Сбросить до начала или до указанной пары "ключ-значение"?)

Hugh Bothwell 30.11.2008 23:14

Этот ответ может быть не лучшим, но это правильный ответ на вопрос ... imo.

aurora 04.03.2014 18:54

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

$awesomePrimes=$primes;

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

Для массива, содержащего 2 миллиона элементов, который использует дополнительные 68 МБ памяти - не конец света, но кажется расточительным.

Hugh Bothwell 30.11.2008 23:23
Ответ принят как подходящий

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

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

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

(хлопая по лбу) Хорошо, это работает - я думал, что foreach () использует собственный указатель массива, но, видимо, нет. делает сбрасывает внутренний указатель массива, что является нечетным побочным эффектом?

Hugh Bothwell 30.11.2008 23:17

Я не уверен, как работает внутренняя реализация foreach, но она поддерживает собственное состояние. Я не помню, чтобы когда-либо использовал указатели на массивы для просмотра списков в PHP.

troelskn 30.11.2008 23:41

Кстати. Как-то странно использовать ассоциативный массив для ваших значений. Я бы использовал простой список, а затем использовал бы in_array (), чтобы проверить, существует ли значение.

troelskn 30.11.2008 23:46

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

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

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

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

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

Другие вопросы по теме