JavaScript Prime Checker не работает

1

Моя контрольная панель не работает. Я думаю, что есть более простые способы сделать эту задачу, но мне нужна функциональность:

Для заданного числа p:

1) Заполните массив numArray цифрами от 2 до p

Я достиг этого:

for (var i=2; i<(p + 1); i++) {
    numArray.push(i);
  };

2) Пока numArray не пуст:

  • добавьте первое число "prime" в numArray к массиву primeArray

  • сплайсинг каждого кратного штриха из numArray

Мой код не использует цикл while, потому что я не уверен, как использовать его для итерации по массиву, но цикл for тоже не работает?

МОЖЕТ ЛЮДИ ПРОСТО ОТВЕТИТЬ С ПРЕДЛОЖЕНИЯМИ, НЕ ПОЛНЫМИ ИСПЫТАНИЯМИ. Определенно, пожалуйста, не пишите полный код, который находит простые числа. Мне больше интересно узнать, как я могу перебирать массив, который я продолжаю нарезать в зависимости от элементов массива, и любые другие указатели о том, как структурировать мой код.

Также я смущен, почему

(numArray[k] % prime == 0)

кажется, пропуская числа?

function checkIfPrime(p) {
  numArray = [];
  primeArray = [];

  for (var i = 2; i < (p + 1); i++) {
    numArray.push(i);
  };

  for (var j = 0; j < numArray.length; j++) {
    if (primeArray.indexOf(numArray[j]) === -1) { //if numArray of j is not already in primeArray

      var prime = numArray[j];
      console.log(prime + " is not in numArray")

      primeArray.push(prime);
      console.log(primeArray);
      numArray.splice(j, 1);
      console.log(numArray);


      for (var k = 0; k < numArray.length; k++) {
        if (numArray[k] % prime == 0) {
          numArray.splice(k, 1);
        };
      }

    }

  };

}


p = 5;
console.log(checkIfPrime(p));
  • 1
    Я создал минимальный воспроизводимый пример для вас
  • 2
    никогда не бегайте с нуля до конца, если вы также собираетесь изменять массив таким образом, чтобы изменить индексы элементов в нем. Либо выполняйте с конца до начала, чтобы любые операции splice не влияли на индексирование того, чего вы еще не достигли, либо сделайте вдвойне тройную или четырехкратную уверенность в том, что в любое время вы пишете numArray. а затем имя функции, вы обязательно обновите свою итерационную переменную по мере необходимости .
Теги:
arrays
for-loop
while-loop

2 ответа

2
Лучший ответ

Поскольку вас больше интересуют предложения, чем рабочий код, давайте начнем с альтернатив.

Проблема заключается в том, что когда вы соединяете элемент из массива, он меняет свою длину. Ничего нового в этом нет, но проблема в том, что вы повторяете один и тот же массив.

Поэтому для заданного массива [2, 3, 4, 5], если j равно 0, prime 2. Таким образом, вы удаляете 2 и 4. Таким образом, новая длина равна 2. Проблема состоит в том, что остальные элементы будут сдвинуты. Таким образом, это будет выглядеть как [3, 5].

Теперь на итерации j будет равно 1. Так оно начнется с 5 и пропустит 5.

Альтернатива:

Вместо удаления элементов присвойте им значение по умолчанию, которое будет пропущено по умолчанию. Таким образом, ваш индекс останется верным, и ваша логика будет простой.

function checkIfPrime(p) {
  var numArray = [];
  var primeArray = [];

  for (var i = 2; i < (p + 1); i++) {
    numArray.push(i);
  };

  for (var j = 0; j < numArray.length; j++) {
    if (numArray[j] !== 0 && primeArray.indexOf(numArray[j]) === -1) { //if numArray of j is not already in primeArray
      var prime = numArray[j];

      primeArray.push(prime);

      for (var k = 0; k < numArray.length; k++) {
        if (numArray[k] % prime == 0) {
          numArray[k] = 0;
        };
      }
    }
  };
  console.log(primeArray)
}


p = 5;
console.log(checkIfPrime(p));

сплайсинг каждого кратного штриха из numArray

Самый простой способ - использовать Array.filter. Если вы манипулируете массивом при выполнении цикла, это усложнит логику. Кроме того, объект должен быть неизменным. Таким образом, вы можете перебрать массив и создать массив temp с необходимыми значениями и заменить значение.

Это можно сделать с помощью array.filter или даже с помощью for.

numArray = numarray.filter(function(num){
  return num % prime !== 0;
})

Предполагая, что numArray будет иметь возможные простые числа, мы можем попытаться минимизировать очевидные не-кандидаты.

var numArray = [2, 3];

for (var i = 8; i<=p; i++) {
  if(i % 2 !== 0 || i % 3 !== 0) {
    numArray.push(i)
  }
}

Кроме того, поскольку простые числа являются фиксированными, мы можем взять длину и предварительно вычислить список простых чисел. Если пользователь вводит большее число, вам просто нужно вычислить числа от предела до нового предела. Таким образом, вы сохраняете некоторое время обработки:

var numArray = [2, 3];

function computePrimes(limit) {
  var init = numArray[numArray.length - 1] || 0;
  for (var i = init; i<= limit; i++) {
    if(isPrime) {
      numArray.push(i);
    }
  }
}

function isPrime(num) {
  for (var i = 3; i< num; i++) {
    if(num % i === 0)
      return true;
  }
  else false;
}

computePrimes(100);

function getPrimeNumbers(num) {
  if(num > numArray[numArray.length - 1]) {
    computePrimes(num);
  }
  // ... Your computation logic
}
1

Как сказал Майк, в целом плохая идея использовать for-loop для итерации по массиву при его изменении.

Я вижу два пути:

Управляйте своими итерационными переменными вручную и убедитесь, что они увеличиваются только тогда, когда это необходимо.

Или используйте метод фильтра массива. Вот базовый пример, чтобы вы начали:

[1,2,3].filter(function(x){return x != 2})
// Will return [1,2]

Имейте в виду, что это вернет новый массив с отфильтрованными значениями, поэтому вам придется его успокоить, выполняя что-то вроде numArray = numArray.filter(...)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню