Как изменить порядок в цикле FOR - PullRequest
15 голосов
/ 27 августа 2010

У меня есть простое утверждение FOR, подобное этому:

var num = 10,
    reverse = false;

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

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

но, если reverse - true, оно должно вернуть [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)
}

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

Ответы [ 11 ]

19 голосов
/ 27 августа 2010
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 ); }

РЕДАКТИРОВАТЬ:

Как отмечено в комментариях ниже, если 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 ); }
7 голосов
/ 27 августа 2010

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

if (reverse) {
    for(i=num-1;i>=0;i--){
        console.log(i)
    }
}
else {
    for(i=0;i<num;i++){
        console.log(i)
    }
}
6 голосов
/ 27 августа 2010
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);
}

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

3 голосов
/ 27 августа 2010
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)
}
2 голосов
/ 03 февраля 2012

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

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 в цикле.

Так что если reversetrue ...

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

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

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

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

1 голос
/ 28 августа 2010

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

for (i = num; --i >= 0; ) ...
1 голос
/ 27 августа 2010

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

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));
}
0 голосов
/ 27 августа 2010

Конечно, в языке, подобном 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, я не знаю, какую именно форму примут определения функций.

0 голосов
/ 27 августа 2010

Вроде работает:

  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);
  }
0 голосов
/ 27 августа 2010

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

C #

    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));

    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...