#When("User fetches the sms template from the templates fetched")
public void user_fetches_the_sms_template_from_the_templates_fetched() {
List<String> jsonResponse = response.jsonPath().getList("$");
for (int i = 0; i < jsonResponse.size(); i++) {
if (getJsonPath(response, "type[" + i + "]").equals("agent_sms_missed_call")) {
agentMissedCallId = getJsonPath(response, "id[" + i + "]");
break;
}
}
for (int i = 0; i < jsonResponse.size(); i++) {
if (getJsonPath(response, "type[" + i + "]").equals("caller_sms_missed_call")) {
callerMissedCallSmsId = getJsonPath(response, "id[" + i + "]");
break;
}
}
for (int i = 0; i < jsonResponse.size(); i++) {
if (getJsonPath(response, "type[" + i + "]").equals("agent_sms_received_call")) {
agentReceivedCallSmsId = getJsonPath(response, "id[" + i + "]");
break;
}
}
for (int i = 0; i < jsonResponse.size(); i++) {
if (getJsonPath(response, "type[" + i + "]").equals("caller_sms_received_call")) {
callerReceivedCallSmsId = getJsonPath(response, "id[" + i + "]");
break;
}
}
for (int i = 0; i < jsonResponse.size(); i++) {
if (getJsonPath(response, "type[" + i + "]").equals("answered_on_ivr_sms")) {
answeredOnIvrSmsId = getJsonPath(response, "id[" + i + "]");
break;
}
}
for (int i = 0; i < jsonResponse.size(); i++) {
if (getJsonPath(response, "type[" + i + "]").equals("answered_on_auto_attendant_sms"))
{
answeredOnAaSmsId = getJsonPath(response, "id[" + i + "]");
break;
}
}
}
Instead of using 6 loops i want to achieve in 1 loop and 6 flag variable so that it goes in IF condition only once. How can i achieve he same ? I am using this rest assured api automation testing.
I'm not familiar with JSON or REST-Assured. My response will reflect that. Also, my response will reflect what my nickname (user name) suggests.
The for loop statements are all the same: for (int i = 0; i < jsonResponse.size(); i++). Assuming nothing done inside the loop changes jsonResponse, you should be able to condense them into one:
#When("User fetches the sms template from the templates fetched")
public void user_fetches_the_sms_template_from_the_templates_fetched() {
List<String> jsonResponse = response.jsonPath().getList("$");
for (int i = 0; i < jsonResponse.size(); i++) {
if (getJsonPath(response, "type[" + i + "]").equals ("agent_sms_missed_call")) {
agentMissedCallId = getJsonPath(response, "id[" + i + "]");
}
if (getJsonPath(response, "type[" + i + "]").equals ("caller_sms_missed_call")) {
callerMissedCallSmsId = getJsonPath(response, "id[" + i + "]");
}
// and 4 more similar if ( ...
This ignores the break statements in each if block of the original code. That might be acceptable. But, it would help to know why the break statements are there.
For efficiency? Once all 6 matches are found, there is no need to continue the loop. This could be important if jsonResponse.size() is large. If small, it's not important.
Is there the possibility of duplicates? If so, is it important to find only the first match?
Other?
If "first match" is required, and jsonResponse.size() is small enough, the "first match" criterion could be preserved by running the for loop with decrement:
for (int i = jsonResponse.size() - 1; i >= 0; i--)
Another suggestion:
#When("User fetches the sms template from the templates fetched")
public void user_fetches_the_sms_template_from_the_templates_fetched() {
List<String> jsonResponse = response.jsonPath().getList("$");
boolean agentMissSet, callerMissSet, agentReceiveSet, callerRecieveSet;
boolean answeredIvrSet, answeredAAset;
agentMissSet = callerMissSet = agentReceiveSet = callerRecieveSet
= answeredIvrSet = answeredAAset = false;
for (int i = 0; i < jsonResponse.size(); i++) {
if (( ! agentMissSet) &&
getJsonPath(response, "type[" + i + "]").equals ("agent_sms_missed_call")) {
agentMissedCallId = getJsonPath(response, "id[" + i + "]");
agentMissSet = true;
}
if (( ! callerMissedSet) &&
getJsonPath(response, "type[" + i + "]").equals ("caller_sms_missed_call")) {
callerMissedCallSmsId = getJsonPath(response, "id[" + i + "]");
callerMissSet = true;
}
// and four more similar if (...
This address the possibility of duplicates issue but not the efficiency issue, if jsonResponse.size() is large. To fix the efficiency issue, add this just before the closing } of the for loop code block:
if ( agentMissSet && callerMissSet && agentReceiveSet
&& callerRecieveSet && answeredIvrSet && answeredAAset ) break;
I don't know what the values of agentMissedCallId, callerMissedCallSmsId, and the other 4 are before the for loop. If they are null or empty, or have some other common default value, that could be used instead of the 6 boolean. This example assumes they will be null:
for (int i = 0; i < jsonResponse.size(); i++) {
if ( agentMissedCallId != null &&
getJsonPath(response, "type[" + i + "]").equals ("agent_sms_missed_call")) {
agentMissedCallId = getJsonPath(response, "id[" + i + "]");
// and 5 more similar ...
That assumes getJsonPath is not going to return null, empty, or whatever is used for the "already set test".
The replacement of the if statement testing 6 boolean, if used, would be an if statement testing 6 String against null, empty, or other default value.
One problem I see with my suggested changes is that the code seems to have gotten uglier. And the 6 if statement and blocks have almost the same code. When I see occurrences of same code, one thing I think of is arrays. Here is how to use two for loops, and arrays:
#When("User fetches the sms template from the templates fetched")
public void user_fetches_the_sms_template_from_the_templates_fetched() {
List<String> jsonResponse = response.jsonPath().getList("$");
String [] id = { agentMissedCallId , callerMissedCallSmsId ,
agentReceivedCallSmsId , callerReceivedCallSmsId ,
answeredOnIvrSmsId , answeredOnAaSmsId
};
String [] type = {"agent_sms_missed_call" , "caller_sms_missed_call",
"agent_sms_received_call" , "caller_sms_received_call",
"answered_on_ivr_sms" , "answered_on_auto_attendant_sms"
};
for (int j = 0; j < id.length; j++) {
for (int i = 0; i < jsonResponse.size (); i++) {
if (getJsonPath(response, "type[" + i + "]").equals(type[j])) {
id [j] = getJsonPath(response, "id[" + i + "]");
break;
}
}
}
}
The above assumes jsonResponse.size() is small, and it's not unreasonable iterate through it 6 times.
The following has the loops nested in the opposite order:
#When("User fetches the sms template from the templates fetched")
public void user_fetches_the_sms_template_from_the_templates_fetched() {
List<String> jsonResponse = response.jsonPath().getList("$");
String [] id = { agentMissedCallId , callerMissedCallSmsId ,
agentReceivedCallSmsId , callerReceivedCallSmsId ,
answeredOnIvrSmsId , answeredOnAaSmsId
};
String [] type = {"agent_sms_missed_call" , "caller_sms_missed_call",
"agent_sms_received_call" , "caller_sms_received_call",
"answered_on_ivr_sms" , "answered_on_auto_attendant_sms"
};
boolean [] matchFound = new boolean [6];
int matchCount = 0;
Arrays.fill (matchFound, false);
for (int i = 0; i < jsonResponse.size () && matchCount < 6; i++) {
for (int j = 0; j < id.length; j++) {
if (matchFound[j]) { continue; }
if (getJsonPath(response, "type[" + i + "]").equals(type[j])) {
id [j] = getJsonPath(response, "id[" + i + "]");
matchFound [j] = true;
matchCount++;
}
}
}
}
Notes:
I assumed getJsonPath returns a String. If it returns some other type of Object, use that type for the id array.
Having tightly coupled arrays suggests room for improvement. Consider having a helper class in which each instance has one id, one type and maybe one matchFound. That way, you can have one array.
I responded to the question in the header: How to reduce the number of for loops. I suspect the code can be improved by making jsonResponse some other Collection, possibly a Map. But, in my judgement, that would be off-topic. Also, I lack sufficient information to be able to elaborate. Perhaps the O/P could followup with a new question. The new question could have some explanation of what the code is to accomplish, and reference this question.
This answer lacks focus. This is the result of several "unknowns". Rather than asking the O/P several questions via the question comments, I attempted to cover several unknowns in a single answer. If the O/P provides more information, I can delete parts of this answer that would then become irrelevant, and otherwise improve this answer.
Another factor in making the answer long is that it is an attempt to show how I might think about this problem.
I am working on this simple program that adds two polynomials. However, I am getting wrong results and could not spot the mistake.
import java.util.LinkedList;
public class Polynomial {
private LinkedList<Term> terms = new LinkedList<Term>();
private class Term {
private int coef;
private int exp;
public Term(int coef, int exp) {
this.coef = coef;
this.exp = exp;
}
public int getCoef() {
return coef;
}
public int getExp() {
return exp;
}
public String toString() {
return (this.coef + "x^" + this.exp);
}
}
public String addPoly(String first, String second) {
LinkedList<Term> otherTerms = new LinkedList<Term>();
String result = "";
String [] termsArray1 = first.split(";");
String [] termsArray2 = second.split(";");
for (int i = 0; i < termsArray1.length; i++) {
String [] temp = termsArray1[i].split("x\\^");
int currentCoef = Integer.parseInt(temp[0]);
int currentExp = Integer.parseInt(temp[1]);
Term currentTerm = new Term(currentCoef, currentExp);
terms.add(currentTerm);
}
for (int i = 0; i < termsArray2.length; i++) {
String [] temp = termsArray2[i].split("x\\^");
int currentCoef = Integer.parseInt(temp[0]);
int currentExp = Integer.parseInt(temp[1]);
Term currentTerm = new Term(currentCoef, currentExp);
otherTerms.add(currentTerm);
}
int i = 0;
int j = 0;
while (true){
if(i == terms.size() || j == otherTerms.size()) {
break;
}
if(terms.get(i).getExp() < otherTerms.get(j).getExp()) {
result += (otherTerms.get(j).toString() + ";");
j++;
}
if(terms.get(i).getExp() > otherTerms.get(j).getExp()) {
result += (terms.get(i).toString() + ";");
i++;
}
if(terms.get(i).getExp() == otherTerms.get(j).getExp()) {
Term temp = new Term((terms.get(i).getCoef() + otherTerms.get(j).getCoef()), terms.get(i).getExp());
result += (temp.toString() + ";");
i++;
j++;
}
}
result = result.substring(0, result.length()-1);
return result;
}
}
::Test::
String s3 = "5x^2;-4x^1;3x^0";
String s4 = "6x^4;-1x^3;3x^2";
Polynomial p = new Polynomial();
System.out.println(p.addPoly(s4, s3));
Expected result: 6x^4;-1x^3;7x^2;-4x^1;3x^0
Actual result: 3x^4;7x^2;-1x^1;10x^0
The problem is that when your loop exits, one of the following can still be true:
i < terms.size()
j < j == otherTerms.size()
And this is the case with your example input. This means that part of one of the terms has not been processed and integrated into the output.
A second problem is that your multiple if statements are not exclusive; after the first if block is executed and j++ has executed, it might well be that j is an invalid index in otherTerms when the second if is evaluated. This should be avoided by turning the second and third if into else if.
Here is a fix for that loop:
while (i < terms.size() || j < otherTerms.size()) {
if(i == terms.size() || j < otherTerms.size() && terms.get(i).getExp() < otherTerms.get(j).getExp()) {
result += (otherTerms.get(j).toString() + ";");
j++;
}
else if(j == otherTerms.size() || i < terms.size() && terms.get(i).getExp() > otherTerms.get(j).getExp()) {
result += (terms.get(i).toString() + ";");
i++;
}
else if(terms.get(i).getExp() == otherTerms.get(j).getExp()) {
Term temp = new Term((terms.get(i).getCoef() + otherTerms.get(j).getCoef()), terms.get(i).getExp());
result += (temp.toString() + ";");
i++;
j++;
}
}
Better approach
Your approach is not really OOP. Ideally, the first expression should serve to create one instance of Polynomial and the other expression should serve to create another instance of Polynomial. Then there should be a method that can add another Polynomial instance to the own instance. Finally there should be a toString method that returns the instance as a string in the required format. Your driver code would then look like this:
Polynomial a = new Polynomial("5x^2;-4x^1;3x^0");
Polynomial b = new Polynomial("6x^4;-1x^3;3x^2");
Polynomial sum = a.addPoly(b);
System.out.println(sum.toString());
This is much more object oriented, and will automatically avoid the code repetition that you currently have.
I have two objects and compare their Strings using an algorithm. I need to store the result, the two objects and the best values. Any suggestions?
void getDistances(Class m1, Class m2) {
Vector[] vector1 = new Vector[m1.getSize()]; // Object from my class
Vector[] vector2 = new Vector[m2.getSize()]; // Object from my class
for (int i = 0; i < vector1.length; i++) {
Class current;
Class next;
current = m1.getInfo(i);
for (int j = 0; j < vector2.length; j++) {
prox = m2.getInfo(j);
calcDist = lev.distance(current.getLabel(), next.getLabel());
System.out.println(current + " <-> " + next + " = " + df.format(calcDist));
if(something here){
// I think it's here the logic ...
}
}
}
}
Any idea will help me. Thanks.
First year CS student. Ive tried to implement an indexOf(String) method in my custom MyStringbuilder class (in this case with a linked list of char). I cant get the right output for finding the query string at the front or not finding it but anything in the middle of of the initial string doesnt work. Specific example below in my test driver.
public int indexOf(String str)
{
int index =-1; //index at which str is first found in linked list string of chars
int count = 0; //num of matches
int firstI = -1;
int sI=0; // dynamic counter variable to allow str.length and for loop to interact
CNode currNode = firstC;
for (int i = 0; i < length; i++)
{
if (currNode.data == str.charAt(sI))
{
if (count < 1)
firstI = i;
count++;
}
if (count == 0 && (sI == str.length()-1))
sI=0;
if (count == str.length())
{
index = firstI;
break;
}
if (count > 0 && currNode.data != str.charAt(sI))
{
sI = 0;
count = 0;
}
currNode = currNode.next; //increment
sI++;
}
return index;
}
TEST DRIVER CLASS
System.out.println("\nTesting indexOf method");
b1 = new MyStringBuilder("who is whoing over in whoville");
String s1 = new String("who");
String s2 = new String("whoing");
String s3 = new String("whoville");
String s4 = new String("whoviller");
String s5 = new String("wacky");
int i1 = b1.indexOf(s1);
int i2 = b1.indexOf(s2);
int i3 = b1.indexOf(s3);
int i4 = b1.indexOf(s4);
int i5 = b1.indexOf(s5);
System.out.println(s1 + " was found at " + i1);
System.out.println(s2 + " was found at " + i2);
System.out.println(s3 + " was found at " + i3);
System.out.println(s4 + " was found at " + i4);
System.out.println(s5 + " was found at " + i5);
You don't set firstI anywhere inside the loop, but it ends up the value you return. This will always return -1.
Additionally, I think you might want to take another look at the variable sI, it doesn't seem to serve any real purpose. If count is ever != sI then you have an issue, so you could just get rid of sI completely.
I did a lot of searching on this subject, but I couldn't find anything usable for my problem: I'm making a simple memory game in Java based on an integer array. I want the array to contain only duplicate entries and no unique ones. Unfortunately most of the questions here are dealing with avoiding or removing duplicate entries, but what about enforcing them?
My code so far looks like this.
public Field[] getField(){
Random r = new Random();
int pool = 16;
ArrayList<Integer> used = new ArrayList<Integer>();
int rand = r.nextInt(pool);
System.out.println("First random: " + rand);
for(int i = 0; i < fields.length; i++){
System.out.println("ITERATION " + i + " STARTED");
while(used.contains(rand)){
System.out.println(rand + " is used, recalculating...");
rand = r.nextInt(pool);
System.out.println("New random is " + rand);
}
fields[i] = new Field(rand);
System.out.println(rand + " added in Field " + i);
int tmp = r.nextInt(fields.length - 1);
System.out.println("First tmp calculated: " + tmp);
while(fields[tmp] != null && i <= fields.length / 2){
tmp = r.nextInt(fields.length - 1);
System.out.println("Field " + tmp + " is used, looking for another...");
}
fields[tmp] = new Field(rand);
System.out.println(rand + " added in temp Field " + tmp);
used.add(rand);
System.out.println("ITERATION " + i + " ENDED");
System.out.println();
}
return fields;
}
fields[] is an array of the type Field (basically has just one member (int id).
If I'm understanding what you're after correctly, I think you're probably making this a lot harder than it has to be.
It is much easier to iterate over your fields array in order and add two Fields of the same value each iteration, then shuffle the array. Something like the following code:
{
...
for (int i = 0; i < fields.length; i += 2)
fields[i] = fields[i + 1] = new Field(r.nextInt(pool));
shuffleFields(fields);
return fields;
}
You can take your pick of shuffling algorithms. The Fisher-Yates shuffle is popular. E.g.:
void shuffleFields (Field[] fields)
{
Random r = new Random();
for (int i = fields.length - 1; i >= 1; --i)
{
int j = r.nextInt(i + 1);
Field t = fields[i];
fields[i] = fields[j];
fields[j] = temp;
}
}