I'm trying to check whether or not all chars in my string are either one of these numbers: 1,2,3,4,5,6,7,8,9,0 OR a decimal point and whether they contain spaces or not. I'm using this piece of code but it's not working and I can't figure out why:
print("Confirming added item")
local validAmountString = true
print(addScreen.amountTxtField.text)
for i = 1, #addScreen.amountTxtField.text do
local c = addScreen.amountTxtField.text:sub(i,i)
print("Char " .. i .. " in the amount textflied is " .. c)
if c == "0" or c == "1" or c == "2" or c == "3" or c == "4" or c == "5" or c == "6" or c == "7" or c == "8" or c == "9" or c == "." then
validAmountString = true
else
validAmountString = false
end
print(validAmountString)
end
if string.gsub(addScreen.nameTxtField.text, "%s+", "") ~= "" and string.gsub(addScreen.amountTxtField.text, "%s+", "") ~= "" and validAmountString == true then
--Proceed...
end
The spaces part is working, but for some reason, when I try to check whether validAmountString == true in my if statement, it stops working. The validAmountString returns the correct boolean value according to my print statement though.
Any help? :)
An easier way to go about this would be string.find
local validAmountString = not addScreen.amountTxtField.text:find( "[^%d%.]" )
I'm afraid I can't tell why validAmountString is not true, but you don't have to compare boolean values.
if (validAmountString) then
--is equivilent to
if (validAmountString == true) then
For checking your strings refer to KingOfGamesYami's answer. He's using something called string patterns btw. Check the Lua reference http://www.lua.org/manual/5.3/manual.html#6.4.1 for details.
"[^%d%.]" matches every character that not a digit or a dot. So if find returns something but nil, your string is invalid
For why your program isn't working as is (in case you want to stick to your complicated way:
You check every character of your string. If it is a number or a dot you asign true, if it's not you asign false.
So let's say you have "12A3" as a string.
Then the final value of validAmountString is true because the last character is a number. So you assign true 2 times, then false for the "A" and after that you asign true again. You mess up your total result.
What you should do here is either assign validAmountString = validAmountString and true, else validAmountString = false so you can never overwrite a false, once set.
The even better and more efficient way would be to simply stop your check once you've hit an invalid character. There is no need to check further characters if you find one invalid.
So simply add a break after validAmountString = false
You do not need the loop to check whether it does or does not have valid characters.
You can simply do tonumber(string). It will return nil if there is any character other than a digit in the string.
Related
this is a problem set from edx python programming.
It has one bug I cannot figure out.
Basically, the logic is if the secretword is equal to a guessword, then, bump up the count.
In the case below, I intentionally put an empty list to test the code. during the first run, it's clear that [''] is not equal to 'a', but the code still execute the if statement.
Am I missing something?
Thank you.
def isWordGuessed(secretWord, lettersGuessed):
'''
secretWord: string, the word the user is guessing
lettersGuessed: list, what letters have been guessed so far
returns: boolean, True if all the letters of secretWord are in lettersGuessed;
False otherwise
'''
count = 0
tempList = []
for element in lettersGuessed:
if element in secretWord and element not in tempList: #to avoid re-counting repetitive char that matches with string
count += 1
tempList.append(element)
if count == len(secretWord):
return True
else:
return False
print(isWordGuessed('a',['']))
Why in your case if is True
Your if statement is evaluated to True because '' in 'put_any_string_here' is always True
Meaning that empty strings are always sub-strings of other strings
Edit
I didn't find a bug in your code. But here's a refactor since you want to revise the code. You can use Lambda expression
Make sure you follow Python's style guide for naming your variables
def is_word_guessed(secret_word, letters_guessed):
l = list(filter(lambda c: c in letters_guessed, list(secret_word)))
return ''.join(l) == secret_word
Each single digit from 0-9 is valid.
two or more digits are valid as long as it doesn't start with 0.
x+y
x-y
x/y
x*y
are valid expressions
Nothing else is a valid expression
Probably what you need based on those rules : https://i.stack.imgur.com/zwgaO.png
import re
userInput = input("Enter expression : ")
if re.match(r'^([0-9]|[1-9][0-9]+)([\+\-\*/]([0-9]|[1-9][0-9]+))*$', userInput):
print("Valid expression")
else:
print("Invalid expression")
Here's some explanation of the regex used :
"^([0-9]|[1-9][0-9]+)([\+\-\*/]([0-9]|[1-9][0-9]+))*$"
First part : ([0-9]|[1-9][0-9]+)
You either match a single digit within range 0-9 or 2+ digits with the first digit within range 1-9 (excluding 0)
Second part : ([\+\-\*/]&first_part)*
First of all you search for any of these operators : + - * /, you need to escape +, - and * characters because they are used in the Python regex syntax. No need to escape the / character though.
The * at the end means you expect the second part to be repeated 0 or more times.
What if I don't want to use regexes ?
userInput = input("Expression : ")
allowedDigits, allowedOPs = [str(a) for a in range(10)], ["+", "-", "*", "/"]
pile = ""
valid = True
for c in userInput:
if c in allowedDigits and pile != "" and pile[0] == "0": valid = False
elif c in allowedDigits: pile += c
elif c in allowedOPs and pile == "": valid = False
elif c in allowedOPs: pile = ""
else: valid = False
if pile == "": valid = False
if valid:
print("Valid Expression !")
else:
print("Invalid Expression !")
This code is pretty simple and straightforward, we just detect the 4 possible fail cases :
The number contains more than one digit and begins with 0
if c in allowedDigits and pile != "" and pile[0] == "0"
There's an operator and no number before
elif c in allowedOPs and pile == ""
There's a non-allowed character
else
Expression ends with an operator (doesn't end with a number)
if pile == ""
Problem
How can I stop the loop from asking "Input string" again without using break? Thanks.
Code
# Remove Break
def main():
inp = 0
while inp <= 0:
inp = int(input("Enter Number: "))
if inp > 0:
string = ""
while string != "you" or string != "me":
string = input("Input string: ")
if string == "you":
stringYou(inp)
break
elif string == "me":
stringMe(inp)
break
def stringYou(inp):
sentence = "I love You"
print(sentence * inp)
def stringMe(inp):
sentence = "You love Me"
print(sentence * inp)
main()
while string != "you" or string != "me":
The condition here is a tautology meaning it will always be true.
There are three interesting cases for your variable string here:
string is equal to "you". The first condition string != "you" is obviously false. The second however isn’t: string != "me". string is "you" which is not equal to "me". So false or true gives you true.
string is equal to "me". With the same reasoning, except in the opposite order, we get true or false which is also true.
string is something else. Both the subconditions are true, so true or true gives true.
So the condition is always true, and the while condition never stops on its own. So you have to break in order to get out of it.
The fix is to simply fix your conditions so that they make sense and the loop properly ends on its own:
while string != "you" and string != "me":
Note the and: Now, the loop only continues when string is neither "you" nor "me". This is equivalent to your break logic where you stopped the iteration when the string became either of those strings.
So it now looks like this:
string = ''
while string != "you" and string != "me":
string = input("Input string: ")
if string == "you":
stringYou(inp)
elif string == "me":
stringMe(inp)
I have text.txt which contains words and numbers.
1. I want to use "for" and "if" for cells or matrices which contain string.
d = reshape(textread('text.txt','%s','delimiter','\t'),2,2)'
if h(1,1)=='apple'
k=1
end
This didn't work.
2. I want to do something like this.
for m=1:size(text)
for n=1:size(text2)
if text2(n,3) contains 'apple' (such as "My apple his, her")
if last word of text2(n,3) is text(m,2)
output(m,1)==text(m,2)
output(m,2)==text(m,1)
end
end
end
end
It is written in non-Matlab way but you know what I want to do.
This type of work might be easy if the text and text2 are matrices of numbers. But they are strings.
How can I perform the same thing I do for numerical matrices?
I think you're looking for the string manipulation utilities. Here are a few:
% Case-sensitive comparison
strcmp('apple', 'apple') == true
strcmp('apple', 'orange') == false
% Case-INsensitive comparison
strcmpi('apple', 'AppLe') == true
strcmpi('apple', 'orange') == false
% Compare first N characters, case sensitive
strncmp('apple', 'apples are delicious', 5) == true
% Compare first N characters, case INsensitive
strncmpi('apple', 'AppLes are delicious', 5) == true
% find strings in other strings
strfind('I have apples and oranges', 'apple')
ans =
8 % match found at 8th character
% find any kind of pattern in (a) string(s)
regexp(...)
Well I'm not going to even begin on regexp...Just read doc regexp :)
I use the following code in PHP to validate if a password includes invalid characters
function validate_password($str) {
if(strlen($str) < 5 || strlen($str) > 30) {
return false;
} else {
return preg_match('/^[-._A-Za-z0-9]*$/',$str);
}
}
I'm trying to do the same in Lua but not sure the best way to check if a string contains only certain characters. My valid characters are alphanumeric with the addition of "-" and "."
local function validate_password(str)
if string.len(str) < 5 or string.len(str) > 30 then
return false
else
if(str:match("%W")) then
-- this isn't right. need to check if alpha numeric or - or .
return false
else
return true
end
end
end
Appreciate any help!
return #str >= 5 and #str <= 30 and str:find('^[%-%.%w_]+$') ~= nil
Note 1: as mentioned in the comments, ~= nil part can be removed as the position returned by find will be evaluated as true (when it's not nil) in logical operators. However, since it's a number, it will fail when used in validate_password(str) == true comparisons (since 1 == true is not true). An alternative is to use not str:find('[^...]') as suggested by Egor.
Note 2: as mentioned in the comments, - and . don't need to be escaped in this particular case. However, since - is a range operator inside square brackets [_-.] is not the same as [-._], as it will match nothing as the range of symbols between _ and . is empty. It's safe to escape - and . even inside square brackets.