Nested loop only access X elements at once - java

I need to access all elements of a list, but only ever 10 elements at most in one go. For this I thought about a nested loop like this:
for (int i = 0; i < 50 / 10; i++) {
for (int k = 0; k < 10; k++) {
paramList.addParam(xyz)
}
sendRequest(paramList);
}
With this nested loop I can access all elements from 0-49 and only ever 10 elements in the inner loop. My problem occurs when the list only hast 49 elements instead of 50. Then I only get up to 39 elements with this logic. Also my best thought on only accessing e.g. 5 elements in the last iteration (list size = 45), is to break the loop, before it goes any further.
So my question is, how can I access all elements in a List with undefined size, but only a maximum of 10 elements in the inner loop (and less if list size doesn't allow 10)?

As an option you can just iterate in outer loop using step of 10 elements:
int step = 10;
for (int i = 0; i < list.size(); i+=step) {
for (int k = i; k < i + step && k < list.size()); k++) {
System.out.println(list.get(k));
}
}

I had to find a reason for your need, breaking the iteration with an inner loop like your snippet doesn't do anything useful, it's still iterate a list.
The only reason I see your logic needed is if you want to call a method after 10 element like :
for (int i = 0; i < 50 / 10; i++) {
for (int k = 0; k < 10; k++) {
System.out.println((i * 10) + k);
}
System.out.println("####");
}
That would make sense, but that second loop is not needed and also give a "complex" code to understand.
As an alternative, you can iterate normally a list and add a condition to execte that method. It gives a much more readable code
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
if( (i + 1)%10 == 0){ //add one to not trigger this on the first iteration
System.out.println("####");
}
}
From your comment:
I retrieve up to 50 records from my database. For each record I need to create a request which will be send in a POST request. Each POST request can contain 10 data requests and I can only send 5 of those request per minute (5*10=50). Since I always fetch TOP 50 data from my database, it can happen that I only get 35 entries instead of 50. To create my requests, I need that data from my database and therefore I have to iterate the whole list, but only ever 10 elements in 1 go to create 1 full POST request
I can see the need here, let's assume you have an instance post that have two method addParam and sendRequest. You need to iterate the list to send String parameters :
int i = 0;
for(String s : params){
post.addParam(s);
if( ++i % 10 == 0){
post.sendRequest();
}
}
//If the last `addParam` was not sended, we check again.
if( i % 10 != 0){
post.sendRequest();
}
Note the condition change outside the loop

as user7 say, you can add a condition to the nested loop
for (int i = 0; i < list.size(); i+=10) {
for (int k = i; k < list.size() && (k-i) < 10; k++) {
System.out.println(k);
}
}

Related

Finding index of an item within a 2D Array

After some research, I found out how to find the index of an item within a 2D Array. However, I'm after just one value, the row number and also what if the item you are looking for appeared more than once?
How would you store the row number of all those times?
for(int j = 0; j < size; j++)
{
if (arr[i][j] == 88)
{
return i; // The value i wanna store
break;
}
}
If the number 88 appears more than once, how can I store all the different locations and later retrieve it?
You could store the values you want in a List.
List<Integer> rows = new ArrayList<>();
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (arr[i][j] == 88) {
rows.Add(i); // The value i wanna store
break; // exit inner loop and continue with next row
}
}
}
i'm after just one value, the row number
But if 88 appears more than once, how can I store all the different
locations and later retrieve it?
Considering you don't know how many duplicated copies of the value you're looking for there could be, I'd suggest using an ArrayList to store the indexes.
create this before the loops:
List<Integer> indexList = new ArrayList<>();
then within the if block simply add the index value for the value you've found to the ArrayList:
if (arr[i][j] == 88){
indexList.add(i);
break;
}
you can then return the ArrayList if your method requires returning the data:
return indexList; // after the loops have finished processing
However, if the method return type is void then you can simply ignore the return indexList;

The most common element in 2d array.How to optimize?

I have this task, find the most commonly seen element in int[][] array and print the number and times repeated.I solved the problem.
A friend of mine said that having 4 for()s is a bad idea.So I decided to try optimising it to remove one or two, but couldn't figure a way.
So here it is:
int cnt, element = arr[0][0], numberRepeats = 0;//cnt-counter,what's the element ,how many times it's repeated
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {//those two for's are for the current element
cnt = 0;//counter is nullified
for (int j2 = i; j2 < arr.length; j2++) {
for (int k = 0; k < arr[j2].length; k++) {//and those two are the compared element
if (arr[i][j] == arr[j2][k]) {//if the current element is the same as the compared element,increase counter
cnt++;
}
}
if (cnt > numberRepeats) {//after the compared element is done comparing and the number of repeats of the current element is more then the lastly checked element
element = arr[i][j];//we get the element ,and how many times it's repeated
numberRepeats = cnt;
}
}
}
}
The only optimisation that I could think of was starting the counting from the current element till the end.
Please give me some more ideas. All the answers I could find were for the 1D array, and they were all pretty much the same code.
You can just iterate your whole array and count the occurrences of every element in a map.
Map<Integer, Integer> elementsCounts = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
Integer count = elementsCounts.get(arr[i][j]])
if(count == null){
count = 0
}
elementsCounts.put(arr[i][j]], count+1)
}
}
Now all it gets is to find the key with the maximum value in the map.
We need to use Map and as well as Set (Set to identify the duplicate elements in a row), only using Map will overlook an edge case scenario where duplicate value in a row may result in incrementing the counter. And finally will be considered as a common value.
Summarizing in below steps:
Populate map with key as a the value of array [i][j] and Map's value as a counter.
IF element is absent in the Map then add key-value pair, Mpa's value as counter initializing from 1.
ELSE, update the element in the Map incrementing the counter with 1
Before incrementing the counter check for duplicate value in the row using Set
Finally, iterate the Map using entrySet() and print only those element whose counter is equal to length of array.
input e.g.:
Integer [][] array = {{1,2,3},{1,4,5,5},{1,5,7}};
output result:
{1}

For loop that shifts array's last value to the left to replace a value x in Java

I have the following method that accepts a generic object (When I use it, I pass an Integer object) and removes the object at that position in the array. Note that my
private currentSize;
private E[] list;
...
public E remove(E obj){
for (int i = 1; i < currentSize; i++)
if( ((Comparable<E>)obj).compareTo(list[i]) == 0){
for(int j = i; j < currentSize; j++)
list[j] = list[j+1];
currentSize--;
return obj;
}
return null;
}
I have two other methods that relate to my method above.
for(int i=1; i <= 10; i++)
list.addLast(i);
The code above adds 10 sequential ints to my array. (This works perfectly. Note that the addLast method parses only a primitive int, because I have it declared like so in addLast() )
for(int i=1; i <= 10; i++){
list.remove(new Integer(i));
}
The code above removes those 10 ints we added before. My remove() method kind of works, it removes all Integer objects from the array except 1.
My output when I call both addLast and then remove methods in another class:
"1 2 3 4 5 6 7 8 9 10
Now removing them all
Current size of list: (should be zero) 1"
That one in front of (should be zero) is not supposed to be there. Please note that I am trying to ignore the 0 index of the array. Also, I would like to know the way of implementing a backwards implementation of my inner-most for loop for(int j = i; j < currentSize; j++). Sort of like [1,2,3,4,5] ... if I want to "remove" #2 in the array, I would start from the end of the array instead of the beginning.
addLast method code:
public void addLast(E obj){
list[currentSize++] = obj;
//System.out.println(currentSize);
}
Print all the objects in array:
for(int x : list)
System.out.print(x + " ");
System.out.println("\n");
Arrays in java are zero bases. So you have to start at zero in your loops:
for(int i=0; i < 10; i++){
list.remove(new Integer(i));
}
And:
private currentSize;
private E[] list;
...
public E remove(E obj){
for (int i = 0; i < currentSize; i++)
if( ((Comparable<E>)obj).compareTo(list[i]) == 0){
for(int j = i; j < currentSize; j++)
list[j] = list[j+1];
currentSize--;
return obj;
}
return null;
}
Your loop in the remove method ignores the first element of the array (1 in your case), so it will never be removed :
for (int i = 1; i < currentSize; i++)
change it to
for (int i = 0; i < currentSize; i++)
Let's look at your addLast method :
list[currentSize++] = obj;
When the list is empty (i.e. currentSize is 0), currentSize++ returns 0 (since it's the postfix increment) and the first element is added to list[0]. Therefore when removing an element from the array you must consider all the indices from 0 to currentSize-1.
That one in front of (should be zero) is not supposed to be there.
Looks like your loop should be i <= currentSize. Ie you are probably not checking whether the item to remove is the last one. So when you ask to remove 1 it isn't found.
But you are not giving enough information.
How to create a Minimal, Complete, and Verifiable example.
I would like to know the way of implementing a backwards
implementation of my inner-most for loop for(int j = i; j < currentSize; j++).
Why? And what does this even mean? If you want to keep the elements in order then your current code puts each one directly into its correct place already. If you don't care about order then you could just move the last element to where the to-be-removed element is by list[i] = list[currentSize--] instead of looping on j.
But again you have not given us enough information about what the external behaviour of your operators is supposed to be or about how external state is represented by internal state.

Gets the number of duplicates in the list - wrong output

How to count duplicates in ArrayList and count only once.
Here is what I have so far:
/**
* Gets the number of duplicates in the list.
* Get the next word. It is at index i. Does it match any of the words with index > i?)
* #return the number of duplicate words in the list
*/
public int countDuplicates() {
int duplicates = 0;
for (int i = 0; i < list.size(); i++) {
for (int j = i; j < list.size(); j++) {
if (list.get(i).equals(j)) duplicates++;
}
}
return duplicates;
}
Here is check output:
Actual: 0
Expected: 3
I am missing something very easy. However, couldn't find what exactly it is.
How to solve this trouble?
You don't get the jth element you just compare to j directly. And as a commenter points out, j should start at i+1 to avoid comparing an element to itself. Therefore, you need to write
public int countDuplicates()
{
int duplicates = 0;
for (int i = 0; i < list.size(); i++) {
for (int j = i+1; j < list.size(); j++) {
if (list.get(i).equals(list.get(j))) duplicates++;
}
}
return duplicates;
}
Should be:
public int countDuplicates()
{
int duplicates = 0;
// TODO: Write the code to get the number of duplicates in the list
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size(); j++) {
if (list.get(i).equals(list.get(j))) duplicates++;
}
}
return duplicates;
}
Use two sets for this:
final Set<X> set = new HashSet<>();
final Set<X> dups = new HashSet<>();
int dupCount = 0;
for (final X x: list) {
if (set.add(x)) // first time the element is seen
continue;
// Dup; see whether it is the first time we see it
if (dups.add(x))
dupCount++;
}
return dupCount;
This relies on the fact that Set's .add() returns true if and only if the set has been modified as the result of the operation. And note that it traverses the list only once.
I can see three problems with your current code:
You are not comparing pairs of elements. You are actually comparing an element with an index.
Your inner loop is comparing element i and element i ... and that would result in a false "duplicate" count.
If you have more than 2 copies of any given element, then you will get too many duplicate counts. (To see why, try to "hand execute" with a list of (say) three identical elements.
In fact, you have to EITHER use an auxiliary data structure (e.g. 2 Sets or a Map) OR modify the input list to avoid counting duplicates more than once.
I would note that your statement of the problem is ambiguous. "... only count each duplicate once" could mean that '[1, 1, 1]' gives either 1 or 2. It depends whether you consider each individual 1 to be a duplicate to be counted once or that we have 1 as one of a set of duplicates ... that must only be counted once.
You are comparing index j value instead of value of list list.get(j).
Do
if (list.get(i).equals(list.get(j)))
instead of
if (list.get(i).equals(j))

Checking rows of 2d ArrayList for specific values

I am trying to scan every row of a 2d array (100x100 sizes) and make sure that every row (and later column) will have only 1 instance of every integer 1 through 100. In the following code I am trying to make sure every row only has one instance of every integer 1 through 100, but obviously the syntax does not work. Is there any method that could push this through or what am I missing?
Thanks for any assistance
for(int i = 0; i<100; i++) {
for (int j=0; j<100 ; j++) {
if(2dARR.get(i).get(j).contains(1) && 2dArr.get(i).get(j).contains(2)(.....)) {
System.out.println("FK");
}
}
}
Dump it into a Set, check that the size of the Array and Set are Equal. If they aren't, there are duplicates. If you get past that test, run a loop through the array and check that all values are greater than 0 and less than 101 (1-100).
for(int i = 0; i<100; i++) {
Set<Integer> numbersInRow = new HashSet<Integer>();
for (int j=0; j<100 ; j++) {
int num = 2dARR.get(i).get(j);
if (num < 1 || num > 100) {
// out of bounds, handle error
}
else {
numbersInRow.add(num);
}
}
// At this point we have the set of numbers found in the row, all guaranteed to be >=1 and <= 100
if (numbersInRow.size() != 100) {
// at least one number appeared more than once
}
}

Categories