Break the Loop of an Array Looping Function (Map, Foreach, etc.)

Break the loop of an Array looping function (map, forEach, etc.)

Array#map, Array#forEach and so on have never been designed to be stopped. That would feel odd since the intent of map as well forEach really is to iterate over all items.

Also i don't think it is possible to notify the caller that a break event has occurred, since it is within a function that is not an integral part of the original loop.

So let's see at a custom method that stops the loop at the first occurrence of true without returning the matching value itself:

Object.defineProperty(Array.prototype, 'untilTrue', {    enumerable: false,    value: function(lambda) {      for(let i in this) {       if(lambda.call(this, this[i])) return;      }    }});
const colours = ["red", "orange", "yellow", "green", "blue", "violet"];
colours.untilTrue(item => { if (item.startsWith("y")) { console.log("The yessiest colour!"); return true; } console.log(item);});

Short circuit Array.forEach like calling break

There's no built-in ability to break in forEach. To interrupt execution you would have to throw an exception of some sort. eg.

var BreakException = {};
try { [1, 2, 3].forEach(function(el) { console.log(el); if (el === 2) throw BreakException; });} catch (e) { if (e !== BreakException) throw e;}

For-each over an array in JavaScript

TL;DR

  • Your best bets are usually

    • a for-of loop (ES2015+ only; spec | MDN) - simple and async-friendly
      for (const element of theArray) {
      // ...use `element`...
      }
    • forEach (ES5+ only; spec | MDN) (or its relatives some and such) - not async-friendly (but see details)
      theArray.forEach(element => {
      // ...use `element`...
      });
    • a simple old-fashioned for loop - async-friendly
      for (let index = 0; index < theArray.length; ++index) {
      const element = theArray[index];
      // ...use `element`...
      }
    • (rarely) for-in with safeguards - async-friendly
      for (const propertyName in theArray) {
      if (/*...is an array element property (see below)...*/) {
      const element = theArray[propertyName];
      // ...use `element`...
      }
      }
  • Some quick "don't"s:

    • Don't use for-in unless you use it with safeguards or are at least aware of why it might bite you.
    • Don't use map if you're not using its return value.
      (There's sadly someone out there teaching map [spec / MDN] as though it were forEach — but as I write on my blog, that's not what it's for. If you aren't using the array it creates, don't use map.)
    • Don't use forEach if the callback does asynchronous work and you want the forEach to wait until that work is done (because it won't).

But there's lots more to explore, read on...


JavaScript has powerful semantics for looping through arrays and array-like objects. I've split the answer into two parts: Options for genuine arrays, and options for things that are just array-like, such as the arguments object, other iterable objects (ES2015+), DOM collections, and so on.

Okay, let's look at our options:

For Actual Arrays

You have five options (two supported basically forever, another added by ECMAScript 5 ["ES5"], and two more added in ECMAScript 2015 ("ES2015", aka "ES6"):

  1. Use for-of (use an iterator implicitly) (ES2015+)
  2. Use forEach and related (ES5+)
  3. Use a simple for loop
  4. Use for-in correctly
  5. Use an iterator explicitly (ES2015+)

(You can see those old specs here: ES5, ES2015, but both have been superceded; the current editor's draft is always here.)

Details:

1. Use for-of (use an iterator implicitly) (ES2015+)

ES2015 added iterators and iterables to JavaScript. Arrays are iterable (so are strings, Maps, and Sets, as well as DOM collections and lists, as you'll see later). Iterable objects provide iterators for their values. The new for-of statement loops through the values returned by an iterator:

const a = ["a", "b", "c"];
for (const element of a) { // You can use `let` instead of `const` if you like
console.log(element);
}
// a
// b
// c

how to stop Javascript forEach?

You can't break from a forEach. I can think of three ways to fake it, though.

1. The Ugly Way: pass a second argument to forEach to use as context, and store a boolean in there, then use an if. This looks awful.

2. The Controversial Way: surround the whole thing in a try-catch block and throw an exception when you want to break. This looks pretty bad and may affect performance, but can be encapsulated.

3. The Fun Way: use every().

['a', 'b', 'c'].every(function(element, index) {
// Do your thing, then:
if (you_want_to_break) return false
else return true
})

You can use some() instead, if you'd rather return true to break.

How to break out from foreach loop in javascript

Use a for loop instead of .forEach()

var myObj = [{"a": "1","b": null},{"a": "2","b": 5}]
var result = false

for(var call of myObj) {
console.log(call)

var a = call['a'], b = call['b']

if(a == null || b == null) {
result = false
break
}
}

Using break and continue in each() and forEach()

Using Array.prototype.some and Array.prototype.every to continue/break out of functional for loops is a good thing to do

[1,2,3,null,5].every(function(v){
if(!v) return false; // this will break out of the loop
// do your regular loopage lulz
});

Cannot break for-loop: Unsyntactic break

Like you yourself suggested, you are still in the map part. That is actually an arrow function expression and you are no longer in in the loop. Think of it as some function you defined elsewhere, but it's a quicker way of calling that function.

You are not using the map function as it is meant to be used in javascript. It isn't meant to be a convenient way to iterate over an array, but rather create a new array from some other array. You should change your usage of map to some form of a loop

`break` and `continue` in `forEach` in Kotlin

Edit:

According to Kotlin's documentation, it is possible to simulate continue using annotations.

fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@ {
if (it == 3) return@lit // local return to the caller of the lambda, i.e. the forEach loop
print(it)
}
print(" done with explicit label")
}

If you want to simulate a break, just add a run block

fun foo() {
run lit@ {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@lit // local return to the caller of the lambda, i.e. the forEach loop
print(it)
}
print(" done with explicit label")
}
}

Original Answer:

Since you supply a (Int) -> Unit, you can't break from it, since the compiler do not know that it is used in a loop.

You have few options:

Use a regular for loop:

for (index in 0 until times) {
// your code here
}

If the loop is the last code in the method

you can use return to get out of the method (or return value if it is not unit method).

Use a method

Create a custom repeat method method that returns Boolean for continuing.

public inline fun repeatUntil(times: Int, body: (Int) -> Boolean) {
for (index in 0 until times) {
if (!body(index)) break
}
}


Related Topics



Leave a reply



Submit