Reputation: 48823
I need to match next element with previous. On condition I would like to continue
iteration. But I don't like copy/paste assignment to previous element:
List<Type> all;
Type prev = null;
for (Type curr : all) {
if (prev == null) {
prev = curr;
continue;
}
if (isBad(curr)) {
prev = curr;
continue;
}
if (! curr.match(prev)) {
prev = curr;
continue;
}
process(prev, curr);
prev = curr;
}
How can I avoid prev = curr
duplication?
I think that solution:
for (Type curr : all) {
if (prev != null && !isBad(curr) && curr.match(prev)) {
process(prev, curr);
}
prev = curr;
}
is cheating because process(prev, curr);
shouldn't have indenting. Error checking logic shouldn't bother with main execution logic (forcing of indentation).
Upvotes: 0
Views: 1155
Reputation: 48823
I think about:
List<Type> all;
Type prev = null;
Type curr = null;
Iterator<Type> iter = all.iterator();
for (; iter.haSNext(); prev = curr) {
curr = iter.next();
if (prev == null)
continue;
if (isBad(curr))
continue;
if (! curr.match(prev))
continue;
process(prev, curr);
}
I wrote blog post about this topic with more detailed examples.
As a result I find out that Java miss goto
statement with which implementation with imposed restrictions would be trivial.
Upvotes: 1
Reputation: 1071
Remove all "continue" from your script.
Either do this by linking the if statements together using "else if" and having process() in an else block at the end, or do so by combining the conditions and swapping the blocks:
for (Type curr : all) {
if (prev != null &&
!isBad(curr) &&
curr.match(prev)) {
process(prev, curr);
}
prev = curr;
}
or
for (Type curr : all) {
if (prev != null) {
}
else if (isBad(curr)) {
}
else if (! curr.match(prev)) {
}
else {
process(prev, curr);
}
prev = curr;
}
Upvotes: 1
Reputation: 158
You could use a for loop with indexes, so you can read 'ahead' and you shouldn't use a variable for the previous one, the last value of i have to be size-1 in this case.
List<Type> all;
Type prev = null;
for(int i=0; i<all.size()-1; i++) {
if(isBad(all.get(i)) {
continue;
}
if(all.get(i).match(all.get(i+1)) {
continue;
}
...
}
Upvotes: 2
Reputation: 5003
Just use OR (||) and put the condition in a method with relevant name:
public void myMethod(){
List<Type> all;
Type prev = null;
for (Type curr : all) {
if (isContinue()) {
prev = curr;
continue;
}
process(prev, curr);
prev = curr;
}
}
private boolean isContinue(){
return (prev == null || isBad(curr) || !curr.match(prev);
}
Upvotes: 1
Reputation: 66
Why not use OR (||).
i.e.
if (prev == null || isBad(curr) || ! curr.match(prev) ) {
prev = curr;
continue;
}
Upvotes: 1
Reputation: 393866
You can eliminate the continue statements and make the code clearer by combining the 3 if statements :
for (Type curr : all) {
if (prev != null && !isBad(curr) && curr.match(prev)) {
process(prev, curr);
}
prev = curr;
}
Upvotes: 1
Reputation: 7166
As far as I can see, you do the same in all the if-s. So you can use the or ||
within the if
:
for (Type curr : all) {
if (prev == null || isBad(curr) || ! curr.match(prev)) {
prev = curr;
continue;
}
process(prev, curr);
prev = curr;
}
Upvotes: 0