4

I need to create a for loop starting at 305 and ending at 397.

for (int i = 305; i < 397; i++) {
    //do stuff
}

The problem is, I need to skip 310, 321, 332, 343, 354, 365, 376, and 387.

I know I can do this by placing the following in the loop:

int[] skip = { 310, 321, 332, 343, 354, 365, 376, 387 };
for (int i2 : skip) {
    if (i != i2) {
        //do stuff
    }
}

But I feel like there is a much more efficient, clean way to achieve this.

Juan Carlos Mendoza
  • 5,736
  • 7
  • 25
  • 50
David
  • 179
  • 1
  • 1
  • 10
  • That should be fine. Go with it. Just keep that array outside both loops. – duffymo Sep 11 '17 at 18:54
  • Make an array list or hashset of your ints to skip and check `contains` in the loop – stephen.vakil Sep 11 '17 at 18:56
  • 1
    I do notice a pattern where every time the 2nd digit is one higher than the 3rd digit, the whole number is ignored. You could use this pattern instead of a skip list. – Luciano van der Veekens Sep 11 '17 at 18:57
  • Looks like a lot of magic numbers to me. Where'd they come from? You should worry about making that clear. – duffymo Sep 11 '17 at 19:00
  • `if (i != i2) { //do stuff }` is wrong. You're executing code for every `i2` that doesn't match `i`, of which there are always at least 7. – shmosel Nov 01 '17 at 23:31

10 Answers10

7

You can also simply add if (i % 11 == 2) continue; at the start of the loop:

for (int i = 305; i < 397; i++) {
  if (i % 11 == 2) continue;
  //do stuff
}

This is because you want to skip a number every 11 steps, starting at 310. So, you want to skip numbers for which i - 310 is a multiple of 11, so for which i - 310 + 11*X is a multiple of 11 whatever X is. So, I've chosen 28 for X, because i - 310 + 11 * 28 equals i - 2. This is easier to read. Finally, the test is simply (i - 2) % 11 == 0, and is equivalent to i % 11 == 2. This method of calculus is named basic modular arithmetic.

Alexandre Fenyo
  • 4,526
  • 1
  • 17
  • 24
6

If you're on java 8, You can use the new streams api with IntStream. You should also use a Set to check for membership quickly. Sets.newHashSet is a helper from guava, but you can also just create a HashSet by hand.

Set<int> intsToSkip = Sets.newHashSet( 310, 321, 332, 343, 354, 365, 376, 387 );
IntStream.range(305, 397)
    .filter(i => ! intsToSkip.contains(i))
    .forEach(i => {
        // do stuff
    })
Alejandro C.
  • 3,771
  • 15
  • 18
3

The Java8 solution could look like this:

List<Intger> valuesToProcess = IntStream.range(305,397).collect(Collectors.toList());
valuesToProcess.removeAll(Arrays.asList(310, 321, 332, 343, 354, 365, 376, 387 ));

for(Integer value : valuesToProcess) {
  // do stuff here
}
Timothy Truckle
  • 15,071
  • 2
  • 27
  • 51
2

The numbers to be skipped are those with i % 11 == 2.

Using this, the Java 8 way is:

 IntStream.range(305, 397)
     .filter(i -> i % 11 != 2)
     .forEach(i -> {
         // do stuff
     });

And for older Java versions do:

for (int i = 305; i < 397; i++) {
    if (i % 11 != 2) {
        // do stuff
    }
}
Thomas Fritsch
  • 9,639
  • 33
  • 37
  • 49
1

There seems to be a pattern of the numbers you need to ignore.

When the 2nd digit is exactly one higher than the 3rd digit, you ignore the number.

for (int i = 305; i < 397; i++) {
    String s = String.valueOf(i);
    if (s.charAt(1) == s.charAt(2) + 1) {
        continue; // ignore
    }
    //do stuff
}
Luciano van der Veekens
  • 6,307
  • 4
  • 26
  • 30
1

One possible solution would be:

import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;

public class Test {
    public static void main(String... args) {
        final Integer[] ignore = new Integer[]{310, 321, 332, 343, 354, 365, 376, 387};
        final List<Integer> ignoreList = Arrays.asList(ignore);
        try (
                final IntStream stream = IntStream.rangeClosed(305, 397)) {
            stream.filter(x -> !ignoreList.contains(x)).forEach(System.out::println);
        }
    }
}

Although, it may be cleaner to create a list from your loop parameters, then remove the ones you don't want to process, then simply loop through that limited list (See the answer by Timothy Truckle).

ManoDestra
  • 6,325
  • 6
  • 26
  • 50
0

If prior to java 8 you can do this:

List<Integer> skip = Arrays.asList(310, 321, 332, 343, 354, 365, 376, 387);

for (int i = 305; i < 397; i++) {
    if(skip.contains(i)){
        continue;
    }
    //do stuff
}
Juan Carlos Mendoza
  • 5,736
  • 7
  • 25
  • 50
0

Since the numbers you are skipping have a difference of 11, you can assign a variable say X, before the loop to -5 and increment the value in the for loop. Whenever the modulo of X is 0 continue the loop

X = -5
for (int i = 305; i < 397; i++) {
if(X%11==0)
    X = X+1;
    continue;
X = X+1;
//your stuff
}
Akash Kumar
  • 81
  • 1
  • 1
  • 10
0

You can intialize skipindex to 0 and increment the skipindex when the skipindex value is reached

int index=0; 
skiplist={310,321,332.....
for (int I=310..){
if (skiplist[index]==I){
index++;
continue;
}
}
//Code to be processed here.
0

The i%11 == 2 solution is cool. In case you don't have a pattern for the numbers you want to skip (or couldn't figure it out like me). There's a clean solution that don't involve a nested lookup loop or hash sets.

int [] ranges = {304, 310, 321, 332, 343, 354, 365, 376, 387, 397};
for (int i = 0; i < ranges.length; i++) {
    int lo = ranges[i] + 1;
    int hi = ranges[i+1];
    for (int j = lo; j < hi; j++) {
        // do stuff
    }
}
xiaofeng.li
  • 8,237
  • 2
  • 23
  • 30