Страницы

Поиск по вопросам

воскресенье, 2 февраля 2020 г.

JavaScript: лишняя итерация цикла do while

#javascript


Этот код, взятый с javascript.ru, ищет все вхождения подстроки "иа":

var str="Ослик иа-иа посмотрел на виадук";
var poisk="иа";
var i=0;
do {
    var x = str.indexOf(poisk,i);
    i=x+1;
    alert(x)
} while (x!=-1)


Недостаток этого кода в том, что он проходит одну лишнюю итерацию, когда indexOf
уже вернул -1. Я модифицировал этот код следующим образом:

var string = "JavaScript и Java - разные языки!";
var substring = "Java";

var nextDesiredSubstringPosition = 0;

while (desiredSubstringPosition!=-1){ // позиция подстроки, которую мы ищмем
    var desiredSubstringPosition = string.indexOf(substring, nextDesiredSubstringPosition);
    if (desiredSubstringPosition === -1 ){break;}
    nextDesiredSubstringPosition = desiredSubstringPosition + 1;// в следующей итерации
начинаем отсюда
}


Лишнюю итерацию я убрал, но получается что условие при while никогда не выполняется
в строке с этим условием, а выход из цикла осуществляется засчет вложенного if. Программа
работает, но код не логичный. Можно ли убрать эту нелогичность, не усложняя код?
    


Ответы

Ответ 1



Почему бы вам не сделать так? var str = "Ослик иа-иа посмотрел на виадук"; var poisk = "иа"; var x, i = 0; while ((x = str.indexOf(poisk,i)) != -1) { alert(x) i=x+1; } Внутри условия цикла вычисляем x и тут же его сравниваем.

Ответ 2



Проблема с циклами while, в отсутствии блока инициализации. Из-за этого решение для них, либо как в соседнем ответе выносить присваивание в проверку, либо как в вопросе добавлять if внутрь цикла. Либо можно просто эмулировать блок инициализации. Пример для цикла с постусловием: var str = "Ослик иа-иа посмотрел на виадук"; var poisk = "иа"; var i = 0; var x = str.indexOf(poisk, i); if (x != -1) { do { console.log(x) i = x + 1; x = str.indexOf(poisk, i); } while (x != -1) } Пример для цикла с предусловием var str = "Ослик иа-иа посмотрел на виадук"; var poisk = "иа"; var i = 0; var x = str.indexOf(poisk, i); while (x != -1) { console.log(x) i = x + 1; x = str.indexOf(poisk, i); } Либо просто воспользоваться циклом for var str = "Ослик иа-иа посмотрел на виадук"; var poisk = "иа"; for (var x = str.indexOf(poisk, 0); x != -1; x = str.indexOf(poisk, x + 1)) { console.log(x); }

Ответ 3



Цикл while не без причины имеет одно выражение, которое интерпретируется как логическое, он в отличии от цикла for предназначен по большей части для итераторов - while( iterator.hasNext() ) { ... } Так же наилучшим образом подходит операций с изменяемым в теле объектом - while( array.length ){ array.pop(); } Или - while( array.length < 5 ){ array.push( { } ) ; } do while отличается от while лишь тем, что его тело гарантированно выполнится один раз. Первым что пришло в голову чтобы продемонстрировать его работу, это специфичность js итераторов, которые лишены метода hasNext - let map = new Map(); let iterator = map[Symbol.iterator](); do { let data = iterator.next(); }while( ! data.done ) Видите как он устроен? Проверку на следующий элемент можно сделать предварительно получив текущий элемент. Тоже самое ниже с использованием while что выглядит не так красиво, ведь в первый раз data инициализируется за пределами цикла, а если условие правдиво, то уже продолжает в теле цикла - let map = new Map(); let iterator = map[Symbol.iterator](); let data = iterator.next(); while( ! data.done ){ data = iterator.next(); } Можно сделать как ниже, но этот код я показываю лишь для того, чтобы Вы раз и навсегда запомнили что так делать нельзя! Такой ленивый код допустимо писать только на форумах для примера, но в серьёзных проектах за такое ругают и уход от такого стиля обычно говорит об опыте человека. let map = new Map(); let iterator = map[Symbol.iterator](); let data = null; while( ! ( data = iterator.next() ).done ){ ... } И самое главное что нужно сказать о do while новичку, это то что он в реальных проектах вообще не используется! Ни одного раза не видел в крутых проектах этот цикл, потому-что правила написания кода диктует поведение, для которого этот цикл просто не нужен. Поэтому не заморачивайтесь на нем и не ищите способы его применения.

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

Отправить комментарий