I am trying to program a method that deletes the first, second and third element of every group of 4 elements. It seems not working at all. Could anyone please help?
public static void reduziereKommentare(List<String> zeilen) {
if (!zeilen.isEmpty()) {
if (zeilen.size() % 4 != 0) {
throw new RuntimeException("Illegal size " zeilen.size() " of list, must be divisible by 4.");
}
for (int i = 1; i <= zeilen.size() % 4; i ) {
zeilen.remove(i);
zeilen.remove(i 1);
zeilen.remove(i 2);
}
}
System.out.println(zeilen);
}
CodePudding user response:
As said in the comments, removing an element impacts the indexing. Whenever I need to do something like this, I either use an Iterator
, or loop backwards.:
for (int i = zeilen.size() - 4; i >= 0; i -= 4) {
zeilen.remove(i 2);
zeilen.remove(i 1);
zeilen.remove(i);
}
Note that I subtract 4 from i
each iteration, so I go back a full block of four each time.
Also note that I remove the largest indexed elements first. If I use i
, i 1
and i 2
inside the loop, I again run into the same issue. I could also have used i
3 times, but this makes it more clear.
CodePudding user response:
My take...does not require the size precondition check but you may want to still catch that if it represents an error of broader scope than this method.
Given this test code...
// Test code
List<String> myList = new ArrayList<>();
for (int i = 0; i < 20; i ) {
myList.add(String.valueOf(i));
}
the 'zeilen' loop can be implemented as ...
// "before" diagnostics
System.out.println(zeilen);
// The 'zeilen' loop
for (int i = 0, limit = zeilen.size(); i < limit; i ) {
if ((i 1) % 4 > 0) zeilen.remove(i/4);
}
// "after" diagnostics
System.out.println(zeilen);
and produces
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[3, 7, 11, 15, 19]
Works with any length list leaving every '4th' element in list.
A few more test cases :
Given Results in
[] []
[0,1] []
[0,1,2,3] [3]
[0,1,2,3,4] [3]
[0,1,2,3,4,5,6,7] [3,7]
[0,1,2,3,4,5,6,7,8] [3,7]
CodePudding user response:
Would it not be easier to simply add every fourth item to a new list and return that? This would also eliminate any repetitive copying that could be involved when removing elements from a list. And the target list can be appropriately sized to start.
public static List<String> reduziereKommentare(List<String> zeilen) {
Objects.requireNonNull(zeilen);
List<String> zeilen1= new ArrayList<>(zeilen.size()/4);
for(int i = 3; i < zeilen.size(); i =4) {
zeilen1.add(zeilen.get(i));
}
return zeilen1;
}
You could also use a stream.
zeilen = IntStream.iterate(3, i ->i < zeilen.size(), i->i =4)
.mapToObj(zeilen::get).toList();
Notes:
- whether the list is empty or the size is not divisible by
4
, this will work. It will just ignore the extra elements. - assigning the result to the original variable will result in the old list being garbage collected.
- I only check for a null argument since that would cause an exception. Of course, if alerting the user of the size is important just add the other check(s) back in.