As part of a program that generates a text output file, I need to insert a predefined number n (which corresponds to the number of required elements) and automatically create conditions among them.
E.g. for n=3, the elements s1, s2 and s3 are generated. What I want to achieve is to generate the following conditions automatically and print them in a text file:
s1<s2 & s1<s3
s2<=s1 & s2<s3
s3<=s1 & s3<=s2
The above conditions cover all possible combinations between the elements. What I have so far is an ArrayList that holds as many elements as the predefined number n and the following code to produce the required results:
int counter = 0;
ArrayList<String> state = new ArrayList<String>();
for (int i=0; i<=n; i++) {
state.add(i,"s"+1));
}
for (int j=1; j<=n; j++) {
for (int i=0; i<(n-1); i++) {
if (i==(n-2)) {
fw.write(state.get(i)+"<"+state.get(counter));
}
else {
fw.write(state.get(i)+"<"+state.get(counter)+" & ");
}
}
counter++;
}
I know that using the counter in this case is not correct, but I cannot think of a way to correctly represent the different conditions.
UPDATE:
Using the following code for testing purposes I managed to get close to the desired outcome:
ArrayList<String> collectStates = new ArrayList<String>();
String activeState,writtenState;
for (int i=0; i<n; i++) {
for (int j=0; j<state.size(); j++) {
if (state.get(i) != state.get(j)) {
activeState=state.get(i)+"<"+state.get(j);
writtenState=state.get(j)+"<"+state.get(i);
if (collectStates.contains(activeState)) {
System.out.print(state.get(i)+"<="+state.get(j));
}
else {
System.out.print(activeState);
}
if (j!=state.size()-1) {
System.out.print(" & ");
}
collectStates.add(writtenState);
}
}
System.out.print("\n");
}
The output I receive is:
s1<s2 & s1<s3
s2<=s1 & s2<s3
s3<=s1 & s3<=s2 &
The only problem is the extra & at the end of the last line, which I don't know yet how to fix.
I found the answer to my question! In the updated section of the description I performed the following addition to remove the extra & symbol:
Old version:
if (j!=state.size()-1) {
System.out.print(" & ");
}
Updated version:
if ((j!=state.size()-1) && ((j!=state.size()-2) || (i!=state.size()-1))) {
fw.write(" & ");
}
The problem appeared always in the last row of the output conditions, thus the newest fix. The output is now exactly as described in the description.
In further detail, what the program did is to remove the identical values:
s1?s1 & s1?s2 & s1?s3
s2?s1 & s2?s2 & s2?s3
s3?s1 & s3?s2 & s3?s3
So by removing:
s1?s1 & we keep s1?s2 & s1?s3
s2?s2 & we keep s2?s1 & s2?s3
s3?s3 we keep s3?s1 & s3?s2 &
As a result, the addition of the new condition is necessary to remove the extra & in the last row.
Related
I have a list view with a hierarchy I theoretically have no knowledge of. I am attempting to accept a String array and create MobileElements for each string in it, but due to the way I've automated (PageFactory) defining my elements via annotations, they cannot use variables. I also don't know that it's valid or proper to define my annotations inside a method.
The code I've written, which obviously does not compile follows:
public void selectLocation(String[] location) {
List<MobileElement> locationsList = new ArrayList<>();
for(int i = 0; i < location.length; i++) {
#iOSFindBy(accessibility = location[i])
#AndroidFindBy(xpath = "//android.widget.TextView[#text='" + location[i] + "']")
locationsList.add(i);
}
for (int i = 0; i < location.length; i++) {
locationsList.get(i).click();
}
}
I'm assuming the proper way to do this is wholly different from the way I've implemented.
My list hierarchy is similar to the following; my end point could vary depending on the branch I go down:
Continent 1
City 1
Room 1
Room 2
City 2
Building 1
Room 1
Room 2
Building 2
Room 1
Room 2
I now look for a matching element. If I don't find it, I swipe further into the list. If the element doesn't exist I obviously run into problems, but not really an issue in my case since that’d be a failing test.
while (!driver.findElementById(currentLocation).isDisplayed()) {
driver.swipe(startX, startY, startX, endY, 100);
}
driver.findElementById(currentLocation).click();
Yes, I also realize .swipe() is deprecated, but it still works for me and I'd rather not rewrite all my code with TouchActions until necessary.
I ended up using the "FindsBys" functions to create an array of all matching elements. I then loop through those elements looking for a match to one of my strings.
#AndroidFindBys({#AndroidFindBy(xpath = "//android.widget.TextView")})
#iOSFindBys({#iOSFindBy(xpath = "//XCUIElementTypeStaticText")})
private List<MobileElement> locationsList;
...
public void selectLocation(String[] location)
{
for(int i = 0; i < locationsList.size(); i++)
for(int p = 0; p < location.length; p++) {
if (locationsList.get(i).getText().equals(location[p])) {
locationsList.get(i).click();
}
}
}
It's not foolproof (if you have duplicate strings at different levels of your hierarchy you may run into issues), but it works for my use-case and should be able to guide anyone looking for a stronger solution.
You can just loop over the elements themselves.
....
for(MobileElement location: locationsList) {
for(int p = 0; p < location.length; p++) {
if (location.getText().equals(location[p])) {
location.click();
}
}
}
I have an array of 24 colors. Occasionally when I generate it I get colors that have the exact same RGB values. What I want to do is find the duplicates in the array and change the value of the match by like 1 or 2. Just so that it doesn't match anymore.
Here is my array of colors. Notice that there are 3 of the exact shade of red. I want each one to be slightly different from each other. Keep the R channel the same but change the G and or B channels to be like 1 or 2 numbers higher.
Color Array: [java.awt.Color[r=255,g=194,b=23], java.awt.Color[r=255,g=0,b=0], java.awt.Color[r=255,g=0,b=0], java.awt.Color[r=0,g=67,b=255], java.awt.Color[r=0,g=255,b=175], java.awt.Color[r=255,g=13,b=10], java.awt.Color[r=255,g=115,b=43], java.awt.Color[r=2,g=92,b=255], java.awt.Color[r=241,g=219,b=255], java.awt.Color[r=255,g=194,b=0], java.awt.Color[r=231,g=210,b=255], java.awt.Color[r=0,g=43,b=255], java.awt.Color[r=255,g=80,b=0], java.awt.Color[r=255,g=205,b=27], java.awt.Color[r=255,g=0,b=9], java.awt.Color[r=205,g=199,b=255], java.awt.Color[r=0,g=44,b=255], java.awt.Color[r=255,g=0,b=0], java.awt.Color[r=21,g=255,b=219], java.awt.Color[r=255,g=199,b=51], java.awt.Color[r=255,g=82,b=2], java.awt.Color[r=215,g=198,b=255], java.awt.Color[r=0,g=255,b=203], java.awt.Color[r=255,g=98,b=28]]
What I was thinking was iterating through the array.
for(int i = 0; i < colorArray.length; i++){
if(colorArray[i] == //not sure what this would be equal to as it will be checking all the values in the array ) {
colorArray[i].getBlue() = matchingColor.getBlue() += 1;
colorArray[i].getGreen() matchingColor.getGreen() += 2; //These are example values just to make sure that they have no match
}
}
Learning the APIs of the Classes you use is really helpful.
for(int i = 0; i < colorArray.length; i++) {
// use while in case the color is black/white. (May thrash for few iterations)
while (colorArray[i].equals(matchingColor)) {
colorArray[i] = (Math.random() < 0.5)?colorArray[i].brighter():colorArray[i].darker();
}
}
Here is a solution using a Set to maintain uniqueness. This saves re-inventing all the functionality to check for duplicates. It takes advantage of the fact that the add method of the Set interface returns true if the object has been added to the set. Under the covers, of course, it uses the equals method of Color.
In the event that a duplicate is found, we repeatedly try modifying the Color a little, by doing a bitwise exclusive-or of its three components, until we come to a unique one.
public void deduplicate(Color[] colors) {
Set<Color> uniqueColors = new HashSet<>();
for (int which = 0; which < colors.length; which++) {
Color originalColor = colors[which];
boolean unique = uniqueColors.add(originalColor);
for (int modifyBy = 1; !unique ; modifyBy++) {
colors[which] = new Color(
originalColor.getRed() ^ modifyBy,
originalColor.getGreen() ^ modifyBy,
originalColor.getBlue() ^ modifyBy);
unique = uniqueColors.add(colors[which]);
}
}
}
Below is the scenario i am trying to automate:
Put all numerical values of the links in a Selenium Weblist & perform an addition and later to verify if the sum of count matches a fixed number.
The issue is that the numerical links returns a number engulfed in braces example:(20)(35)(16)(15)
I need to first trim these brackets & fetch only the numbers & then perform the addition i.e: 20+35+16+15
Later i need to assert the total against the number i.e: Assert.assertequals(sum,'86')
List<WebElement> lists=driver.findElements(By.cssSelector("span.ndocs"));
for (int i=0; i<lists.size(); ){
String trimmed_value=lists.get(i).getText();
trimmed_value=lists.get(i).getText().trim().substring(trimmed_value.indexOf("(") + 1);
trimmed_value=lists.get(i).getText().trim().substring(0, trimmed_value.indexOf(")"));
System.out.println(trimmed_value);
int numerical_value = Integer.parseInt(trimmed_value);
i++;
}
Till now i am able to get the elements, iterate them & able to remove the braces & get the numbers, I am stuck upon how to perform the addition operation & then do an Assert for the count.
Any help will be much appreciated here.
Try using below code.
Initialize a variable outside the method and add every trimmed_value to it as explained below.
import assertEquals(import static org.junit.Assert.assertEquals;)
int expected_value=86;
int numerical_value=0;
List<WebElement> lists = driver.findElements(By.cssSelector("span.ndocs"));
for (int i = 0; i < lists.size(); ) {
String trimmed_value = lists.get(i).getText();
trimmed_value = lists.get(i).getText().trim().substring(trimmed_value.indexOf("(") + 1);
trimmed_value = lists.get(i).getText().trim().substring(0, trimmed_value.indexOf(")"));
System.out.println(trimmed_value);
numerical_value =numerical_value+Integer.parseInt(trimmed_value);
i++;
}
assertEquals(expected_value, numerical_value);
I have this code I am persisting like that:
for (int i = 0; i < listofplusieurdrapage.size(); i++) {
persist(listofplusieurdrapage.get(i));
}
I have two values in
litsofplusieurdrapage => litsofplusieurdrapage.get(0) = 1
=>litsofplusieurdrapage.get(1) = 2
but when i check the database I found them in this order:
2
1
and when I add just a system.out.println to the code I have the good order
for (int i = 0; i < listofplusieurdrapage.size(); i++) {
System.out.println(" Persist : " + listofplusieurdrapage.get(i));
persist(listofplusieurdrapage.get(i));
}
1
2
do you have an explication of the problem ?
and how I can keep the good order with out adding the system.out.println to my code ?
public void persist(Object object) {
em.persist(object);
}
There is no ordering in tables, see for example this question and other links there.
If you need an order on the listofplusieurdrapage, you must specify the ordering, see for example this question.
I don't know regex very well. I am trying to find strings that start with digits 2,3,5 or 7, are 1,3,7 or 9 throughout the middle, and end with 3 or 7.
My attempt was [2357][1379]*[37]. It does not work. I'd appreciate a correction. Remember that this is meant for the Java String.matches() function. Thanks in advance
for (int s = 0; s < primes.size(); ++s) {
String p = primes.get(s);
if (!p.matches([REGEX GOES HERE])) {
System.out.println(p);
primes.remove(s);
}
}
The standard method of iterating over a collection you remove from in the loop is to iterate downwards that way removals don't affect the index of subsequent elements:
for (int s = primes.size() - 1; s >= 0; s--) {
String p = primes.get(s);
if (!p.matches("[2357][1379]*[37]")) {
System.out.println(p);
primes.remove(s);
}
}
No need now to worry about implications of removing elements.
The following code "works" just fine:
List<String> primes = new ArrayList<String>();
primes.add("1");
primes.add("2");
primes.add("7");
primes.add("23");
primes.add("213");
primes.add("243");
primes.add("2113");
primes.add("2193");
for (int s = 0; s < primes.size(); ++s) {
String p = primes.get(s);
if (!p.matches("[2357][1379]*[37]")) {
System.out.println(p);
primes.remove(s);
}
}
It outputs:
1
7
243
You may have expected it to output:
1
2
7
243
However, the primes.remove(s) is messing up your loop. That can't really be the intent of your design. (But who knows?!) The following is one of many solutions to avoid messing up your loop:
for (String prime : new ArrayList<String>(primes)) {
if (!prime.matches("[2357][1379]*[37]")) {
System.out.println(prime);
primes.remove(prime);
}
}
Hi I am not sure I am mistaken .. but i dont see anything wrong in your initial pattern for example
String aa = "[2357][1379]*[37]";
String bb = "2977313";
boolean matches = Pattern.matches(aa, bb);
System.out.println("1) "+matches);
I started with no 2 and then ended with no 3 and added 1379 in between and it works as expected. Please correct me if i am wrong
Your regex works well. However, remove shifts any subsequent elements to the left, so the String ordinarily at position s + 1 is moved to s, so the next element to check is at position s instead of s + 1. Fix:
for (int s = 0; s < primes.size();) {
String p = primes.get(s);
if (!p.matches("[2357][1379]*[37]")) {
System.out.println(p);
primes.remove(s);
} else
++s;
}