Reputation: 3081
List data = [1, 2, 3];
data.forEach((value) {
if (value == 2) {
// how to stop?
}
print(value);
});
I tried return false;
which works in jQuery, but it does not work in Dart.
Is there a way to do it?
Upvotes: 85
Views: 82724
Reputation: 47
You CAN empty return from a forEach to break the loop;
List<int> data = [1, 2, 3];
int _valueToBePrinted;
data.forEach((value) {
if (value == 2) {
_valueToBePrinted = value;
return;
}
});
// you can return something here to
// return _valueToBePrinted;
print(value);
anyway you shouldn't...
the catch is, you can't return anything in the entire forEach loop
//This don't work
data.forEach((value) {
if (value == 2) {
_valueToBePrinted = value;
return;
}
if (value == 1) {
return value;
}
});
Upvotes: -1
Reputation: 2008
Somebody suggest where()
but it is not a general replacement for forEach()
with break capability
(where
is however a correct replacement for the use case showed in the example of the question. I, on the other hand, focus on the question in the title)
The functionality of foreach()
but with an equivalent of break
, is given by any()
: to continue the loop you return false, to stop you return true; the result of any() can be ignored. I think it is more similar to each()
in jquery (but in dart to stop you return true).
To have a loop with the index, but also the possibility in case of break the loop, I use the following extension:
extension IterableUtils<E> on Iterable<E> {
/**
Similar to Iterable.forEach() but:
- with an index argument
- with the optional capacity to break the loop, returning false
Note: as for the return clause, you can omit it, as with forEach()
*/
void forEachIndexed(Function(E element, int index) f) {
int index = 0;
for (E element in this) {
if (f(element, index) == false) break;
index++;
}
}
}
void main() {
List list = ["a", "b", "c"];
list.forEachIndexed((element, index) {
print("$index: $element");
//Optional:
if (element == "b") return false; //break
});
}
Upvotes: 0
Reputation: 338
Here is a full sample by for-in loop, that close to forEach style.
void main(){
var myList = [12, 18, 24, 63, 84,99];
myList.forEach((element) {
print(element);
if (element ==24); //break; // does not work
});
for(var element in myList) {
print(element);
if (element==24) break;
}
}
Upvotes: 1
Reputation: 3575
The callback that forEach takes returns void so there is no mechanism to stop iteration.
In this case you should be using iterators:
void listIteration() {
List data = [1,2,3];
Iterator i = data.iterator;
while (i.moveNext()) {
var e = i.current;
print('$e');
if (e == 2) {
break;
}
}
}
Upvotes: 16
Reputation: 19494
Using Multiple Loop
Break Outer Loop
OUTER: for (var i = 0; i < m.length; i++) {
for (var j = 0; j < m[i].length; j++) {
if (m[i][j] < 0) {
print("Negative value found at $i,$j: ${m[i][j]}");
break OUTER;
}
}
}
Continue Outer Loop
outer: for (var v in a) {
for (var w in b) {
if (w == v) continue outer;
}
print(v);
}
Upvotes: 1
Reputation: 2073
based on Greg Lowe post, I used where for my project and also it works.
var data = [1, 2, 3];
data.where((val) => val != 2).forEach(print);
Upvotes: 3
Reputation: 11205
Breaking a List
List<int> example = [ 1, 2, 3 ];
for (int value in example) {
if (value == 2) {
break;
}
}
Breaking a Map
If you're dealing with a Map
you can't simply get an iterator from the given map, but you can still use a for
by applying it to either the values or the keys. Since you sometimes might need the combination of both keys and values, here's an example:
Map<String, int> example = { 'A': 1, 'B': 2, 'C': 3 };
for (String key in example.keys) {
if (example[key] == 2 && key == 'B') {
break;
}
}
Note that a Map doesn't necessarily have they keys as [ 'A', 'B', 'C' ]
use a LinkedHashMap if you want that. If you just want the values, just do example.values
instead of example.keys
.
Alternatively if you're only searching for an element, you can simplify everything to:
List<int> example = [ 1, 2, 3 ];
int matched = example.firstMatching((e) => e == 2, orElse: () => null);
Upvotes: 24
Reputation: 16301
It is also possible to implement your example using forEach() and takeWhile().
var data = [1, 2, 3];
data.takeWhile((val) => val != 2).forEach(print);
Upvotes: 51
Reputation: 7393
You can also use a for/in, which implicitly uses the iterator aptly demonstrated in the other answer:
List data = [1,2,3];
for(final i in data){
print('$i');
if (i == 2){
break;
}
}
Upvotes: 120
Reputation: 26064
Dart does not support non-local returns, so returning from a callback won't break the loop. The reason it works in jQuery is that each() checks the value returned by the callback. Dart forEach callback returns void.
http://docs.jquery.com/Core/each
Upvotes: 5