Как в последовательности цифр подсчитать, сколько раз появляется цифра, значение которой ровно на единицу меньше, чем у предыдущей цифры?

#javascript #arrays #algorithm #for-loop #reduce

#javascript #массивы #алгоритм #for-цикл #уменьшить

Вопрос:

код:

 function OneDecremented(num) { 
  num = num.toString()
  var count = 0

  for(i = 1; i < num.length; i  ) {
    if(num[i - 1] - num[i] === 1){
      count  
    }
  }
  return count

}
console.log(OneDecremented(9876541110)) 

итак, я изо всех сил пытаюсь понять две вещи:

  1. в чем разница между i и num[i]
  2. Я не понимаю, как происходит вычисление внутри оператора if, может ли кто-нибудь разбить его?

извините, если эти вопросы звучат слишком глупо, я новичок в JS и не мог разобраться в арифметических вычислениях. Спасибо, что уделили вам время.

Комментарии:

1. Добро пожаловать в SO, и я рад, что вы получили успешный ответ. Было бы вежливо признать / поддержать любых других пользователей, которые нашли время, чтобы помочь, ответив.

2. @Mitya … У OP недостаточно репутации для голосования (даже один раз проголосовал против); но позвольте мне помочь.

3. @PeterSeliger Спасибо, очень любезно. Я не понимал (даже после всего этого времени), что новички еще не могут голосовать. Это кажется странным; я бы подумал, что их следует поощрять реагировать на предоставленные ответы (в дополнение к принятию ответа.)

4. @Mitya Я пытался, но это мне не позволило. Спасибо за ваше время <3

5. Не беспокойтесь — я не знал, что вы не можете голосовать как новичок.

Ответ №1:

Этот код плохо написан по нескольким причинам, но самое главное, он пропускает i ссылку глобально, поэтому давайте начнем с лучшей версии:

 function OneDecremented(num) {
  var str = num.toString();
  var count = 0;
  for(var i = 1; i < str.length; i  ) {
    if(str[i - 1] - str[i] === 1)
      count  ;
  }
  return count;
}
 

К строкам в современном JS можно обращаться как к массивам, а индекс возвращает символ в index позиции:

 if(str[i - 1] - str[i] === 1)
// is the same as
if ((str.charAt(i - 1) - str.charAt(i)) === 1)
 

После извлечения каждого символа код выполняет неявное преобразование «символ в число«, благодаря - оператору, но если бы вместо этого было a , он бы объединил два символа в виде строки (так что будьте осторожны).

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

Цикл начинается с 1 , и он проверяет, что char at i - 1 , который на первой итерации является char at index 0 , минус текущий char 1 , означает, что текущий char на единицу меньше предыдущего.

Когда это так, счетчик подводит итог.

Комментарии:

1. Спасибо за объяснение! Теперь это имеет больше смысла 🙂

Ответ №2:

Андреа и Митя уже справились с этим.

Следующим шагом может быть переход на подход, основанный на первом классе, например, с использованием определенного Array метода, такого как reduce .

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

Для примера, предоставленного OP, можно написать две функции: фактический метод, который получает счетчик, и вышеупомянутую функциональность редуктора первого класса. Поскольку reduce это стандартный способ обработки массивов, приоритет аргументов редуктора / обратного вызова также хорошо указан…

 [/* ... */].reduce(function(accumulator, currentValue, currentIndex, currentlyProcessedArray) {

  // implement reducer/aggregation/accumulator logic here.

  // the return value serves as the
  // new `accumulator` value within
  // the next iteration step.

  // thus, always return something! ... e.g ...

  return (accumulator   currentValue); 
});
 
 function aggregatePrecursorAndDecrementedSuccessorCount(count, char, idx, arr) {

  const precursorValue = Number(arr[idx - 1]);
  const incrementedCurrentValue = (Number(char)   1);
  const isValidCount = (precursorValue === incrementedCurrentValue);

  return (count   (isValidCount ? 1 : 0));
//return (count   Number(isValidCount)); // cast boolean value to either 1 or 0.
}

function getPrecursorAndDecrementedSuccessorCount(int) {
  return String(int) // - assure/typecast always a/into string value.
    .split('')       // - split string value into an array of single characters.
    .reduce(aggregatePrecursorAndDecrementedSuccessorCount, 0);
}

console.log(getPrecursorAndDecrementedSuccessorCount(9876541110)); 
 .as-console-wrapper { min-height: 100%!important; top: 0; } 

Комментарии:

1. Спасибо, что познакомили меня с другим подходом! Действительно помогает 🙂

Ответ №3:

в чем разница между i и num[i]

i является ключом итерации, т.Е. 0, 1, 2 и т.д., поскольку в строковом числе столько символов. num[i] это символ с индексом i в строке, т. Е. num[i] Где i 0 == 9 (символ в строке с индексом 0).

Я не понимаю, как происходит вычисление внутри оператора if, может ли кто-нибудь разбить его?

Это говорит: если вычисление числа по индексу i-1 строки за вычетом текущего рассматриваемого числа (по индексу i в строке) минус равно 1, затем увеличьте count .

Шаг за шагом для фактического используемого числа:

  • 9 — не имеет предыдущего символа; вычисление (не определено — 9) не равно 1
  • 8 — предыдущий символ равен 9; (9 — 8) == 1; приращение count
  • 7 — то же самое
  • 6 — то же самое
  • 5 — то же самое
  • 4 — то же самое
  • 1 — предыдущий символ равен 4; вычисление (4 — 1) не равно 1
  • 1 — предыдущий символ равен 1; вычисление (1 — 1) не равно 1
  • 1 — то же самое
  • 0 — предыдущий символ равен 1; (1 — 0) == 1; приращение count