Vlad Otrocol
Vlad Otrocol

Reputation: 3190

Detect last iteration in FOR OF loop in ES6 javascript

There are multiple ways of finding out the last iteration of a for and for...in loop. But how do I find the last iteration in a for...of loop. I could not find that in the documentation.

for (item of array) {
    if (detect_last_iteration_here) {
        do_not_do_something
    }
}

Upvotes: 54

Views: 72294

Answers (10)

Wilt
Wilt

Reputation: 44413

You could also use Array.prototype.at() with -1
See MDN on Array.prototype.at() here for reference.

Your example would simply look like this:

for (item of array) {
    if (item === array.at(-1)) {
        // do_not_do_something
    }
}

Upvotes: 0

ani627
ani627

Reputation: 6057

Using the following approach you can find the last iteration in a for...of loop:

let iCount = 0;

for( const obj of arrObjects) {
  iCount = iCount + 1;
  if (iCount < arrObjects.length) {
    // Some code to execute on first to (last - 1) elements
  }
  else {
    // Some code only for the last element
  }
}

Upvotes: 0

Yashawant Sawant
Yashawant Sawant

Reputation: 43

const chain = ['ABC', 'BCA', 'CBA'];
let findOut;
for (const lastIter of chain) {
    findOut = lastIter;       //Last iteration value stored in each iteration. 
} 

console.log(findOut);

Upvotes: 0

AkshayBandivadekar
AkshayBandivadekar

Reputation: 840

With ES6, by calling the entries() method on the array you can do it =>

const array = [1, 2, 3];
for (const [i, v] of array.entries()) {
    //Handled last iteration
    if( i === array.length-1) {
        continue;
    }
    console.log(i, v)// it will print index and value
}

Upvotes: 5

Luiz Felipe
Luiz Felipe

Reputation: 997

A more generalized alternative, firmly based in composition principles, is implement another iterator using a generator function. This will, in fact, compose these two iterators.

The new iterator will basically delegate the actual yielding of the values to the original iterator. The difference is that the former will alyaws be “one step ahead” of the latter. By doing so, the new iterator will be capable of verify, for each element, if the iteration has stopped with the next one.

function* withLast(iterable) {
  const iterator = iterable[Symbol.iterator]();
  let curr = iterator.next();
  let next = iterator.next();
  while (!curr.done) {
    yield [next.done, curr.value];
    [curr, next] = [next, iterator.next()];
  }
}

Notice that, in the first iteration, next is called twice. For each of the following iterations, next is always called once, only for the element that corresponds one step ahead of the current iteration.

Learn more about the JavaScript iteration protocols to learn more about that implementation.

A little more concrete example:

function* withLast(iterable) {
  const iterator = iterable[Symbol.iterator]();
  let curr = iterator.next();
  let next = iterator.next();
  while (!curr.done) {
    yield [next.done, curr.value];
    [curr, next] = [next, iterator.next()];
  }
}

const arr = [1, 2, 3];
for (const [isLast, element] of withLast(arr)) {
  console.log(`${element} ${isLast ? 'is' : 'is not'} the last.`);
}

As concepts like index or the actual length of the iterator – the latter which isn't even a thing in some corner cases as infinite iterators – aren't used in this solution, this approach is well suited for any kind of iterator.

Another example:

function* withLast(iterable) {
  const iterator = iterable[Symbol.iterator]();
  let curr = iterator.next();
  let next = iterator.next();
  while (!curr.done) {
    yield [next.done, curr.value];
    [curr, next] = [next, iterator.next()];
  }
}

// Generator function that creates a "generic" iterator:
function* gen() {
  yield 'a';
  yield 'b';
  yield 'c';
}

for (const [isLast, element] of withLast(gen())) {
  console.log(`${element} ${isLast ? 'is' : 'is not'} the last.`);
}

Upvotes: 2

Shidersz
Shidersz

Reputation: 17190

One possible way is to initialize a counter outside the loop, and decrement it on every iteration:

const data = [1, 2, 3];
let iterations = data.length;

for (item of data)
{
    if (!--iterations)
        console.log(item + " => This is the last iteration...");
    else
        console.log(item);
}
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

Note that !--iterations is evaluated as !(--iterations) and the expression will be true when iterations=1.

Upvotes: 35

Maksym Dudyk
Maksym Dudyk

Reputation: 1163

The simpliest way to find the last loop and, let's say, get rid of the last comma insert during iterration is to compare the length of array with the index of its last item.

const arr = ["verb", "noun", "pronoun"];

for (let item of arr) {
    if (arr.length -1 !== arr.indexOf(item)) {
        console.log('With Commas');
    } else {
        console.log('No Commars');
    }
}

Upvotes: 0

J S
J S

Reputation: 1198

One approach is using Array.prototype.entries():

for (const [i, value] of arr.entries()) {
    if (i === arr.length - 1) {
        // do your thing
    }
}

Another way is keeping a count outside the loop like Shidersz suggested. I don't think you want to check indexOf(item) though because that poses a problem if the last item is duplicated somewhere else in the array...

Upvotes: 65

Thomas Skubicki
Thomas Skubicki

Reputation: 637

There doesnt seem to be anything the the spec for for..of for this. There seems to be two work-arounds:

If you can, just push a marker to the end of the array and act on that marker, like so:

myArray.push('FIN')
for (el of myArray){
    if (el === 'FIN')
        //ending code
}

Alternatively, you can use the below to get an index you can use in tandem with an Array.length

enter link description here

Upvotes: 1

Matt H
Matt H

Reputation: 1971

If you want to change your loop behavior based the specific index, then it's probably a good idea to use an explicit index in your for-loop.

If you simply want to skip out on the last element, you can do something like

for (item of array.slice(0, -1)) {
    //do something for every element except last
}

Upvotes: 0

Related Questions