I have a problem where .contains() is not returning true when looking for a substring.
See the below code snippet and image which shows variable values for the following code. The problem I have is that the expression returns false, when I think it should obviously be true.
if (this.fileName.toLowerCase().contains(extension.toLowerCase())){
return true;
}
I have encountered this today, after searching the web I can't see anything obvious that is going on here.
I have tried the same using literals, but still does not evaluate to true:
if ("Android App Image.jpg".toLowerCase().contains("jpg".toLowerCase())){
return true;
}
I have broken it down further so the result is in a boolean:
boolean result = ("Android App Image.jpg".contains("jpg"));
if (result) {
return true;
}
The result is true, so .contains is not the issue, rather it appears my if() doesn't evaluate the boolean as true and doesn't cause return true to execute.
I now think it's an issue with my while loop (full function below). Does the enumeration run asynchronously?
public boolean isImage(){
String[] imageExtensions = {"jpg", "png", "bmp", "gif"};
for (String extension: imageExtensions) {
if (this.localFileURLString != null && this.localFileURLString.toLowerCase().contains(extension)){
return true;
}
boolean result = ("Android App Image.jpg".toLowerCase().contains("jpg".toLowerCase()));
if (result) {
return true;
}else{
Log.i("TEACH", "If evaluated false");
}
}
return false;
}
UPDATE 1/2:
I have trimmed down the entire function, with hard coded literals and no longer using fast enumeration, which still returns false when I expect it to return true:
public boolean isImage(){
String[] imageExtensions = {"jpg", "png", "bmp", "gif"};
for (int x = 0; x < imageExtensions.length; x++) {
// String extension = imageExtensions[x];
boolean result = ("Android App Image.jpg".toLowerCase().contains("jpg".toLowerCase()));
if (result) {
return true;
}else{
Log.i("TEACH", "If evaluated false");
}
}
return false;
}
The function does not returns true or does the "If evaluated false" Log get executed, it just jumps straight to the last line of the function (return false;) after evaluating the line if (result) {... it's as if the if breaks the loop.
UPDATE 2/2:
Quite simply, even the most simple of if statements inside my function would cause the code to jump to the last line of the function and return false. For example:
if(true == true){
return true
}
This happened when stepping through in debug mode and also coded logs show the same result when not attached to a bugger.
After returning from the function every carries on as normal. No errors or warnings.
re-installing Android Studio, trying different simulators and physical Android devices didn't resolve the issue.
Renaming the function didn't resolve the issue.
Changing the return type of the function from boolean to Boolean did resolve the issue.
I'm well aware of the differences in these types, but I'm still perplexed as to to why this would this this problem. I can only assume changing the method signature in this way solved is something funky was happening at compile time.
I'll leave the question open for now, as even though changing the return type "fixed" the issue for me, i'm still not satisfied i'll know why... probably never will.
Hopefully somebody much more knowledgable on these sorts of issues can enlighten is all!
Why don't you try using:
if (this.fileName.toLowerCase().contains(extension.toLowerCase()==true){
}
Your search term produces false positive . Cause the file name string can have a substring that matches the extension.
To avoid this you can prepend the search terms by a dot.
String[] imageExtensions = {".jpg", ".png", ".bmp", ".gif"};
This will apperantly solve your problem .
It can produce false positive if there's any irregular use of DOT in the file name.
Hope it helps.
Related
I have been taking the test on Codility, and trying this exercise:
https://app.codility.com/programmers/trainings/4/disappearing_pairs/
A string S containing only the letters "A", "B" and "C" is given. The string can be transformed by removing one occurrence of "AA", "BB" or "CC".
Transformation of the string is the process of removing letters from it, based on the rules described above. As long as at least one rule can be applied, the process should be repeated. If more than one rule can be used, any one of them could be chosen.
Write a function:
class Solution { public String solution(String S); }
that, given a string S consisting of N characters, returns any string that can result from a sequence of transformations as described above.
For example, given string S = "ACCAABBC" the function may return "AC", because one of the possible sequences of transformations is as follows:
Also, given string S = "ABCBBCBA" the function may return "", because one possible sequence of transformations is:
Finally, for string S = "BABABA" the function must return "BABABA", because no rules can be applied to string S.
Write an efficient algorithm for the following assumptions:
the length of string S is within the range [0..50,000];
string S is made only of the following characters: "A", "B" and/or "C".
Here is the code that I tried with a score of 83:
public String solution(String S) {
boolean notAA = false;
boolean notBB = false;
boolean notCC = false;
while(S.length()==0 || true){
if (S.contains("AA")){
S = S.replace("AA", "");
} else {
notAA = true;
}
if(S.contains("BB")){
S = S.replace("BB", "");
} else {
notBB = true;
}
if(S.contains("CC")){
S = S.replace("CC", "");
} else {
notCC = true;
}
if(notAA && notBB && notCC){
break;
}
}
return S;
}
I could not obtain the 100% score because of this:
even_palindrome1 big palindrome of even length
✘WRONG ANSWER got CACABACABABCBACBACBA.. expected ""
Codility doesn't show me the string example or any other information.
I was reading and reviewing but I still do not understand why I am not getting the right output. My assumption is when I delete the first combination of letters, the string needs to be in a specific state or a specific combination of letters to work correctly and the problem is the palindrome even string.
But, if my assumption is correct, I don't really understand the real cause or root reason for this.
Thanks in advance for your help.
You should reset notAA, notBB and notCC inside your loop.
Consider, for example, ABCCBA. In your first pass, notAA and notBB are set to true, leaving ABBA. In the second pass, notAA and notCC are set to true, leaving AA. Your program would then break out with an available pair because all three conditions are set to true.
You have to set notAA, notBB and notCC to false inside the loop, not before it. The way you are doing it, you find all three, you end the loop.
Say S is ABCCBA.
You set notAA and notBB to true, because AA and BB cannot be found; then you replace CC, giving you ABBA.
Next loop, you set notAA to true again, remove BB, producing AA, and set notCC to true. Now all three are true (since notBB remained true since the first iteration), and you break the loop.
The result is AA, which should have reduced further; but because the program thought there was no AA, but it appeared after notAA was set, you get the wrong value.
In fact, this can be simplified: you just need a single flag changed, which starts before the loop as true; then use while (changed). At the top of the loop, set it to false, and set it to true every time you successfully replace a substring. You do not need three separate ones, since they all do effectively the same job.
I am doing an assignment which asks me check the given phone number whether it matches the pattern(the pattern is ddd-ddd-dddd) and the numbers are within 0 to 9. I want to use for loop and substring method, but I have no idea how to use them. This code is what I've done so far.
public static boolean phoneNum(String s){
boolean a = false;
boolean b = false;
String phone = s.substring(1,4)+s.substring(5,8)+s.substring(9);
for(int i =0; i<phone.length(); i++){
y = Character.isDigit(s1.charAt(i));
}
if(s.charAt(4)=='-' && s.charAt(8)=='-' && b==true){
a = true;
return a;
}
return a;
}
If I can add for loop, where should it be?
You are asking how to improve the quality of this code, so let's give some ideas:
change its name to meet java conventions, like isValidPhoneNumber()
you don't need to "carry forward" the results of a previous check. Your method should simply return false immediately whenever it finds a condition to be violated. If all tests pass, you then simply return true in the end.
In other words: what makes your code hard to read and overly complicated are those single character named boolean variables. They mainly add confusion. And keep in mind that your code is ignoring that y variable for example. And even if y is just a typo that could still be simplified.
And to make that clear: avoid using names like a or b. These names mean nothing. They don't tell the reader anything about the purpose of that variable.
I am facing something strange here. Please help me understand if I am missing something. My if condition was supposed to be:
if(configuredPdf == true)
But by mistake I had written:
if(configuredPdf = true)
And my Eclipse compiler does not ask me to correct it. Then I assume there is no compile time or checked exception. So:
(configuredPdf = true)
Returns a boolean?
Yes, configuredPdf = true assigns true to your variable and returns true. Therefore if (configuredPdf = true) is a valid syntax even though it's usually a bug.
It's safer to use if (configuredPdf) to avoid this kind of typo.
An assignment is an expression which returns the value you assigned. e.g. a = b = true will assign true to a and b.
The reason boolean type was added was to avoid this sort of bug. In C for example you can write
if (a = 1)
and anything non-negative is true.
While you can still make a mistake with boolean types, instead of writing
if (a == true)
if (b == false)
you can write
if (a)
if (!b)
A more common example is
for(String line; ((line = br.readLine()) != null;) {
// process the line.
}
An assignment expression's result is always the value that was assigned, including when assigning to a boolean. This is covered by JLS§15.26:
At run time, the result of the assignment expression is the value of the variable after the assignment has occurred.
So yes, configuredPdf = true assigns true to configuredPdf, and the result of that expression is true.
Similarly, x = y = 5; assigns 5 to y, and the result of y = 5 is 5, which is then assigned to x.
Fundamentally, what you wanted was:
if (configuredPdf)
There's never any need to compare a boolean variable with true or false, just use the if (theVariable) (for comparing with true) or if (!theVariable) (for comparing with false). Getting in that habit will protect you from inadvertent assignment.
The only time actually comparing boolean values is useful is when they're both variables, e.g. if (thisFlag == thatFlag) or if (thisFlag != thatFlag).
To avoid accidental assignment in that situation, either:
Use a linter that checks for this
"double bang" the first flag:
if (!!thisFlag == thatFlag)
...although as you pointed out if you can accidentally type = instead of ==, presumably you can accidentally type ! instead of !! :-)
Use an old C idiom (this is what I use):
if (!thisFlag == !thatFlag)
What is happening is when the compiler comes to the if condition in your code, it assigns 'configuredpdf' to be true. Thus the condition
if(configuredpdf = true)
Becomes true and the loop executes successfully. However, the problem arises when we DON'T want this loop to be true. At that time when, for a given input, the compiler parses the if condition, it forcibly becomes true and executes the code written in if condition executes even if the data entered does not agreeing. That is why you will find that your code has a bug at the if condition.
configuredPdf must be a boolean for if(configuredPdf = true) to compile.
configuredPdf = true will assign true to configuredPdf and thus if will succeed.
I am really confused by a CodingBat Java exercise. It's suppose to return true if the given string contains an appearance of "xyz" where the xyz is not directly preceeded by a period (.). So "xxyz" counts but "x.xyz" does not.
xyzThere("abcxyz") → true
xyzThere("abc.xyz") → false
xyzThere("xyz.abc") → true
I couldn't figure this out for the life of me so I just looked up a solution online and I'm so confused why this works. Any wanna help clarify? I added some comments on the code as to what I am having trouble with.
public boolean xyzThere(String str) {
int pos =0;
while ((pos = str.indexOf("xyz")) >= 0) { `
The while ((pos = str.indexOf("xyz")) >= 0) { confuses me here. I tried this without the double brackets and it didn't work. Does the double brackets do some kind of casting to an int or something? Also how does pos even get assigned to something in a while statement, does it run the part on the right first then assigns it?
if (pos == 0)
return true;
if (str.charAt(pos-1) != '.')
return true; // found it
// xyz was preceded by a period so skip over this match
str = str.substring(pos+1);
I am so confused how it can even reach str = str.substring(pos+1); I thought I could just take this out entirely but it broke the entire program. Since it's an if statement and it has no brackets to make it a block statement, how or when is this reached, and what is the logic behind it? What the purpose of this statement, as it seems so pointless to me. Even if it does get reached in the code, what does it do?
}
return false; // no luck
}
For any readers, here's the xyzThere problem: http://codingbat.com/prob/p136594
Since you were initially looking for any solution, here's a non-looping solution:
public boolean xyzThere(String str) {
return str.replaceAll("\\.xyz", "").contains("xyz");
}
Regarding double parens: if you remove the double parens, then it won't compile, because the compiler interprets that as trying to assign str.indexOf("xyz") >= 0 to the pos variable, and the types, boolean and int respectively, don't match.
You will notice that assignment is at the bottom of java operator precedence - without the extra parens, it will occur last: http://www.cis.upenn.edu/~palsetia/java/precedenceTable.html
unle
Regarding assignment in a loop - yes this is valid. The value assigned to pos is then compared with 0.
Regarding str = str.substring(pos+1);. This is how the posted solution is removing ".xyz" from the string which finally determines whether the string still contains "xyz".
Regarding the if statement
if (str.charAt(pos-1) != '.')
return true; // found it
Without brackets, the implied scope of the if statement if the next statement. The style here is generally considered back practice for just the reason you've found and should be rewritten as either:
if (str.charAt(pos-1) != '.') {
return true;
}
or
if (str.charAt(pos-1) != '.') return true;
while ((pos = str.indexOf("xyz")) >= 0) {
indexOf returns -1 if the string is not found so this is going to continue looking so long as an "xyz" is found in the string. See later for how it makes sure this is another occurrence rather than the same one again.
The extra bracket is to stress that there is also an assignment going on here. pos is being updated to the start of the "xyz" that was found (or -1 if no more).
if (pos == 0)
return true;
It is allowed at the start - I guess.
if (str.charAt(pos-1) != '.')
return true;
If there is not a "." just before it then we're done.
str = str.substring(pos+1);
Throw away everything up to and including the "x" of the discovered "xyz". Makes sure that next time around we don't find the same one again.
return false;
We got to the end without finding one - it must not be there.
The following code snippet needs "double brackets" (really double parentheses -- it pays to be precise because brackets are a different character) because the parens group different parts of what amounts to a mathematical expression. What you think are double brackets are actually single parens grouping different parts of the expression from what you probably think they're grouping.
while ((pos = str.indexOf("xyz")) >= 0)
^-----^
^------------------------^
^-------------------------------^
If you switch to an IDE instead of the simple text editor that you're probably using, the IDE will highlight matching parentheses so you can see which opening paren is related to which closing paren. There's no casting or other magic going on. Parentheses, brackets, angle brackets, and curly braces. are just there to show the beginning and end of particular groups of things, whether it's an expression, an expression within an expression, a data set, etc.
Basically, this peice of code seems to behaving differently when I move the breakpoints
int checker = something.length(); /* something is the value of an edittext */
boolean badInput = false;
if(checker == 0)
{
badInput = true;
}
if(checker > 12)
{
badInput = true;
}
*1 if(badInput = false)
{
*2 /* A lot of
code to do
if the
input is GOOD */
}
else
{
/* Alert that the input is BAD */
}
When I enter a 2 digit number into the edittext with the first breakpoint (1), badInput gives false, as it should.
Here is the problem: when I do exactly the same with only the second breakpoint (2), the code goes onto the else statement, and alerts, even though the input is exactly the same.
Anybody know why this might be?
This:
if(badInput = false)
Should be:
if(badInput == false)
Or preferrably:
if (!badInput)
The first is performing an assignment, not a comparison. The overall result of the expression badInput = false is also the value assigned (false) so it will never enter the body of that if.
It's not really clear what you mean by entering data "with" a breakpoint, but fundamentally the problem is in your code.
You should have:
if(!badInput)
or
if(badInput==false)
(the first one is better)
Simple typo error,
if(badInput = false)
should be
if(badInput == false)
you want a compare not assign.
What you check boolean variable with == operator ?!!
You have to check as following :
if(!badInput) //for false value
or
if(badInput) //for true value