15

I've a simple FOR statement like this:

var num = 10,
    reverse = false;

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

when reverse is false I want it to return something like [0,1,2,3,4,5,6,7,8,9]

but, when reverse is true, it should return [9,8,7,6,5,4,3,2,1,0]

Which is the most efficient way to get this result, without checking every time if reverse is true or false inside the loop?

I don't want to do this:

var num = 10,
    reverse = false;

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

I would like to check reverse only one time outside the loop.

palswim
  • 11,856
  • 6
  • 53
  • 77
Raspo
  • 1,048
  • 1
  • 7
  • 20
  • 1
    What are you actually trying to do? Because if it's create an array, or loop on an array, there is always the javascript function reverse http://www.w3schools.com/jsref/jsref_reverse.asp which you can call – CaffGeek Aug 27 '10 at 19:55
  • 1
    w3schools is not so good. Check out [w3fools](http://w3fools.com/). – DwB Feb 03 '12 at 17:07

12 Answers12

19
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:

As noted in the comments below, if i is not declared elsewhere and you do not intend for it to be global, then declare it with the other variables you declared.

And if you don't want to modify the value of num, then assign it to i first.

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 ); }
mikemaccana
  • 110,530
  • 99
  • 389
  • 494
user113716
  • 318,772
  • 63
  • 451
  • 440
  • 1
    Nice. I was going to suggest `for(i = num; i--;) log(i);`, but [the consensus](http://stackoverflow.com/questions/1340589/javascript-are-loops-really-faster-in-reverse) seems to be that your method is fastest. – palswim Aug 27 '10 at 17:21
  • To the op: be aware that `num` will be modified when printed in reverse, so be sure to make a copy of the original value if you plan to use that value in the future. – Cristian Sanchez Aug 27 '10 at 18:04
  • @Daniel - Very true. If that's a concern, here's quick replacement for the `else` statement: `else{i=num;while(i--)log(i)};` – user113716 Aug 27 '10 at 18:33
  • don't forget to declare `var i` somewhere – cobbal Aug 27 '10 at 18:54
  • @cobbal - The OP didn't declare it in the question, so I assume it is declared elsewhere, or is intended to be global. If not, then yes, it could be added to the OP's other declarations. `var num = 10, reverse = false, i;` – user113716 Aug 27 '10 at 18:59
7

Try use 2 loops:

if (reverse) {
    for(i=num-1;i>=0;i--){
        console.log(i)
    }
}
else {
    for(i=0;i<num;i++){
        console.log(i)
    }
}
Ivan Nevostruev
  • 28,143
  • 8
  • 66
  • 82
  • 2
    I was about to post pretty much the same thing as this. This seems to me the most natural and readable solution, and is also efficient, the reverse flag is tested only once and not every time through the loop. – Jay Aug 27 '10 at 17:18
6
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);
}

This is equivalent to the following, which is more readable, but less compact:

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:
Actually, these two solutions are not identical, because the first one has an additional increment operation. Still, it is negligible from performance point of view. If you really want to get a compact solution that has the best performance, you can do the following (not for the faint of heart):

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

This has the advantage of having a single control structure, a single test in each loop, and a single iterator addition. It is not as fast as having an iterator increment/decrement, but only marginally so.

Roy Sharon
  • 3,488
  • 4
  • 24
  • 34
  • lol. You wrote yours as I was writing mine (the page refreshed when new answers were posted). :P I abuse ternary statements. Glad to see someone who writes like me. – XstreamINsanity Aug 27 '10 at 16:56
  • No abuse of ternaries there... I consider it abuse only if you don't use the return value of the ternary expression like condition ? doSomething() : doSomethingElse(); --- Completely outside the point, though... – Ruan Mendes Aug 27 '10 at 17:40
  • I like your solution, but I found the patrick's one more clear. – Raspo Aug 27 '10 at 20:43
3
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)
}
Jerome
  • 1,162
  • 1
  • 6
  • 12
2

I just came across the need for this the other day. Here's how I did it:

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

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

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

No need for separate loops, and no need to do math to calculate the proper i in the loop.

So if reverse is true...

  • i (which represents our first item) becomes num - 1, so we're now starting on what would have been the last item

  • num (which represents out of bounds) becomes -1, so we're now stopping on what would have been the first item

  • direction is -1, which means it will decrement when we do i += direction

So by swapping our starting point with our ending point and changing the alteration of i from 1 to -1, we'll be going up or down based on those modifications.

1

I think this meets your requirements:

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));
}
Bernard
  • 7,908
  • 2
  • 36
  • 33
1

Here's how I've always done reverse loops:

for (i = num; --i >= 0; ) ...
Mike Dunlavey
  • 40,059
  • 14
  • 91
  • 135
0

And what's your problem with:

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

}

James Curran
  • 101,701
  • 37
  • 181
  • 258
0

Roy's is similar to mine, but here's what I was thinking. I'll give you what I wrote in C# and how I think it translates to 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);
    }

And here's another way
Javascript

    var num = 10,
        reverse = false;

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

    }
XstreamINsanity
  • 4,176
  • 10
  • 46
  • 59
  • 1
    All of these still test the reverse flag on every iteration of the loop. – Jay Aug 27 '10 at 17:17
  • lol. My bad, I didn't see that part in the question. Thanks for letting me know. However, to the OP, if you're worried about performance, I wouldn't. I'll think of something else though, if I can. – XstreamINsanity Aug 27 '10 at 17:30
  • I think the OP wasn't aware of ternary statements, thinking they'd have to have an if/else in their loop. I'm still thinking about another way though. – XstreamINsanity Aug 27 '10 at 17:34
0

It seems to work:

  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);
  }
abele
  • 437
  • 4
  • 15
0

Surely in a language like Javascript there must be a way to define a local function and use that in the loop?

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

Not knowing Javascript though, I don't know what actual form the function definitions would take.

dash-tom-bang
  • 17,383
  • 5
  • 46
  • 62
0
//reverse a number
let c = [2,3,5,67,4]
let sum = '';
let d = c.toString().split('')
console.log(d)
for(let i = d.length-1; i >= 0; i--) {
    sum += d[i]
}
console.log(sum)
Dmitry Kuzminov
  • 6,180
  • 6
  • 18
  • 40