Как изменить порядок в цикле FOR

У меня есть простой оператор FOR:

var num = 10,
    reverse = false;

for(i=0;i<num;i++){
    console.log(i);
}

когда reverse является ложным Я хочу, чтобы он возвращал что-то вроде [0,1,2,3,4,5,6,7,8,9]

но если reverse истинно, он должен возвратить [9,8,7,6,5,4,3,2,1,0]

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

Я не хочу этого делать:

var num = 10,
    reverse = false;

for(i=0;i<num;i++){
    if(reverse) console.log(num-i)
    else console.log(i)
}

Я хотел бы проверить reverse только один раз за пределами цикла.

Ответы

Ответ 1

var num = 10,
reverse = false;

if(!reverse) for( var i=0;i<num;i++) log(i);
else         while(num-- )      log(num);

   // to avoid duplication if the code gets long
function log( num ) { console.log( num ); }

EDIT:

Как отмечено в комментариях ниже, если i не объявлен нигде, и вы не собираетесь его глобальным, тогда объявите его с другими объявленными вами переменными.

И если вы не хотите изменять значение num, сначала назначьте его i.

var num = 10,
reverse = false,
i;

if(!reverse) for(var i=0;i<num;i++) log(i);   // Count up
else         {var i=num; while(i--) log(i);}  // Count down

function log( num ) { console.log( num ); }

Ответ 2

Попробуйте использовать 2 цикла:

if (reverse) {
    for(i=num-1;i>=0;i--){
        console.log(i)
    }
}
else {
    for(i=0;i<num;i++){
        console.log(i)
    }
}

Ответ 3

var num = 10,
    reverse = false;

for (var i = 0, n = reverse?num-1:0, d = reverse?-1:1; i < num; i++, n+=d) {
    console.log(n);
}

Это эквивалентно следующему, более читабельному, но менее компактному:

var num = 10,
    reverse = false;

var start = reverse ? num-1 : 0,
    end   = reverse ? -1 : num,
    step  = reverse ? -1 : 1;
for (var i = start; i != end; i += step) {
    console.log(i);
}

Edit:
На самом деле эти два решения не идентичны, потому что первый имеет дополнительную операцию приращения. Тем не менее, он пренебрежимо мал с точки зрения производительности. Если вы действительно хотите получить компактное решение с лучшей производительностью, вы можете сделать следующее (не для слабонервных):

var num = 10,
    reverse = false;

for (var r=reverse, i=r?num-1:0, n=r?-1:num, d=r?-1:1; i!=n; i+=d) {
    console.log(i);
}

Это имеет то преимущество, что имеет единую структуру управления, один тест в каждом цикле и одно дополнение итератора. Это не так быстро, как увеличение/уменьшение итератора, но только незначительно.

Ответ 4

var start; var end; var inc;
if (reverse) {
    start = num-1; end = 0; inc = -1;
}
else {
    start = 0; end = num-1; inc = 1;
}
for(i=start;i!=end;i+=inc){
    console.log(i)
}

Ответ 5

Я только наткнулся на необходимость этого на днях. Вот как я это сделал:

var num = 10,
    i = 0,
    direction = 1, 
    reverse = false;

if(reverse)
    i = num + (direction = num = -1);

for(; i !== num; i += direction) {
    console.log(i);
}

Нет необходимости в отдельных циклах, и не нужно делать математику для вычисления правильного i в цикле.

Итак, если reverse есть true...

  • i (который представляет наш первый элемент) становится num - 1, поэтому мы теперь начинаем с того, что было последним элементом

  • num (который представляет собой пределы) становится -1, поэтому мы теперь останавливаемся на том, что было бы первым элементом

  • direction - -1, что означает, что он уменьшится, когда мы сделаем i += direction

Итак, заменив нашу начальную точку нашей конечной точкой и изменив изменение i от 1 до -1, мы будем идти вверх или вниз на основе этих изменений.

Ответ 6

Я думаю, это соответствует вашим требованиям:

var num = 10;
var reverse = false;
var diff = 0;

if (reverse) {
    diff = num - 1;
}

for (i = 0; i < num; i++) {
    console.log(Math.abs(diff - i));
}

Ответ 7

Вот как я всегда делал обратные циклы:

for (i = num; --i >= 0; ) ...

Ответ 8

И какая у вас проблема с:

   if (reverse)
   {
     for(i=num-1; i>=0;i--){ 
          console.log(i);
      }
   }
   else
   {
      for(i=0;i<num;i++){ 
         console.log(i) 
      } 
   }

}

Ответ 9

Рой похож на мою, но вот что я думал. Я дам вам то, что я написал на С#, и как я думаю, что это переводится в Javascript.

С#

    int num = 10;
    bool reverse = true;

    for (int i = reverse ? num : 0; (reverse ? 0 : i) < (reverse ? i : num); i += reverse ? -1 : 1)
    {
        Console.Write((reverse ? i - 1 : i).ToString());
    }
    Console.ReadKey();

Javascript

        var num = 10,
        reverse = true;

    for (int i = reverse ? num : 0; (reverse ? 0 : i) < (reverse ? i : num); i += reverse ? -1 : 1)
    {
        console.log(reverse ? i - 1 : i);
    }

И вот еще один способ

Javascript

    var num = 10,
        reverse = false;

    for (int i = 0; i < num; i++)
    {
      console.log((reverse ? abs(-num + (i + 1)) : i));

    }

Ответ 10

Кажется, что работает:

  var num = 10;
  var z = 1;
  var k = -10;
  if (reverse ){
    k = -1;
    z = -1;
  }
  for(int i = 0; i < 10; i++){
    console.log(num+i*z+k);
  }

Ответ 11

Разумеется, на языке, таком как Javascript, должен быть способ определить локальную функцию и использовать ее в цикле?

function SubtractFrom(val, subtractor) {
    return val - subtractor;
}

function PassThrough(val) {
    return val;
}

var num = 10;
var processor = reverse ? SubtractFrom(num-1) : PassThrough;

for (i = 0; i < num; i++) {
    console.log(processor(i));
}

Не зная Javascript, хотя я не знаю, какую фактическую форму будут выполнять определения функций.