If substring in string, when substring has multiple values - python

I know there is a way to work around it, but I want to understand the underlying logic as to why this doesn't work.
It's a very simple statement, and it only returns as True when the first substring in the "or list" is shown.
for i in list:
if (substring1 or substring2 or substring3) in string:
print(string + " found!")
What am I missing here? I would think the or conditions would equal true if any substring was found in the string. As is, I'm only coming up as true if substring1 is found in string, and no substring2 or substring3.

substring1 or substring2 or substring3
Assuming that substring1 is not the empty string, this expression evaluates to substring1 because substring1 is truthy. This is then checked to see if it's in string. The other substrings have no effect on the statement.
In other words, the ors are evaluated before the in, and the or evaluates to the first truthy value it finds (this is called short-circuiting). You can't use in that way to check whether multiple substrings are in a string.
You want:
substring1 in string or substring2 in string or substring3 in string
Or:
substrings = (substring1, substring2, substring3)
if any(s in string for s in substrings):

>>> string = 'hello'
>>> s1 = 'he'
>>> s2 = 'll'
>>> s3 = 'o'
>>> (s1 or s2 or s3)
'he'
>>> 'he' in string
True
The problem here is that you are first evaluating (s1 or s2 or s3) which will give you s1 if s1 does not evaluate to false. In a boolean context, empty strings evaluate to false:
>>> s1 = ''
>>> (s1 or s2 or s3)
'll'
What you want is s1 in string or s2 in string or s3 in string, this will return true if at least one of the substrings is in the string.

Its because python uses lazy evaluation... for example...
def error():
raise ArithmeticError
print "nothing" or error()
Will Print "nothing" because it evaluates to True in python code does not check error, which would ordinarily raise an error and stop the script from continuing...
print False or error() #raises error and breaks script
(substring1 or substring2 or substring3) #returns the first true value

The correct code should be
for i in list:
if (substring1 in i ) or (substring2 in i) or (substring3 in i):
print(i + " found!")
The above code can find substring when they have multiple values.
(substring1 or substring2 or substring3)
This expression will return the first item in brackets that is not null.
For example, if subtring1 is not null, it will return the value of substring1.
When substring1 is not null,
(substring1 or substring2 or substring3)
equals to
substring1

You probably want any:
if any(substr in string for substr in substrs):
# At least one match

Related

Python: check str using regex

I need to write func to check str.
If should fit next conditions:
1) str should starts with alphabet - ^[a-zA-Z]
2) str should contains alphabet, numbers, . and - ([\w]+*.-)
3) str should ends with alphabet or number - \w$
4) length of str should be from 10 to 50
def check_login(str):
flag = False
if match(r'^[a-zA-Z]([\w]*.-)\w${10, 50}', str):
flag = True
return flag
It returns False to all combinations.
I think, error in 2 condition. I know, that I can use [a-zA-Z0-9\.-]+, but it does not indicate a mandatory entry.
How can I fix that?
Use:
match(r'^[a-zA-Z][\w.-]{8,48}\w$', str)
If you don't want to match _:
match(r'^[a-zA-Z][a-zA-Z0-9.-]{8,48}[a-zA-Z0-9]$', str)
If you want at least one dit, one dash, one letter and one digit:
^[a-zA-Z](?=.*-)(?=.*\.)(?=.*[0-9])[a-zA-Z0-9.-]{8,48}[a-zA-Z0-9]$
Where (?=....) is a lookahead, a zero-length assertion, that makes sure we have its content in the string.
Straight-forward approach with re.search() function:
import re
def check_login(s):
return bool(re.search(r'^[a-zA-Z][a-zA-Z0-9.-]{8,48}[a-zA-Z0-9]$', s)
and re.search(r'\.[a-zA-Z0-9]*-|-[a-zA-Z0-9]*\.', s[1:-1]))
# test cases
print(check_login('al-De.5af3asd.2')) # True
print(check_login('3lDe.5af3asd.2')) # False
print(check_login('al-De.5a')) # False
print(check_login('xl-De.5a3333333333333')) # True
You can try this regex:
import re
final_string = [''] if not re.findall("^[a-zA-Z]{1}[a-zA-Z0-9\-\.]{9,49}\d$|\w$", s) else re.findall("^[a-zA-Z]{1}[a-zA-Z0-9\-\.]{9,49}\d$|\w$", s)
if final_string[0] == s:
#success, a match has been found.
pass

questions about if,what does 'if +some variable:'(without any condition) mean?

def string_to_int_list(s):
L1=[]
for i in s.split(','):
if i:#what does this line mean?
L1.append(int(i))
return L1
I want to convert string to list,and if I delete 'if i',it will remind me that ValueError: invalid literal for int() with base 10: ''
if i has a value, the condition will return true, if the value of i is None (empty), it will return false. It's the same as i != None.
Also I test that if the split function returns an empty string "" it will not pass the if condition.
For check if a string is numeric (0 - 9) you can use str.isdigit()
str.isdigit()
Return true if all characters in the string are digits and there is at least one character, false otherwise.
For 8-bit strings, this method is locale-dependent.
This code works:
def string_to_int_list(s):
L1=[]
for i in s.split(','):
if i and i.isdigit():#what does this line mean?
L1.append(int(i))
return L1
a = "1,2,3,q,43,hello"
b = string_to_int_list(a)
print b
It will return [1, 2, 3, 43]
Note that I remove indentation to return because it has no sense inside the loop.
What you are doing here is splitting your string by , and then converting to integer if you see a valid value.
Let's say your 1,2,3,4,,,5
What the script is returning you a list of [1,2,3,4,5]
You should try what if condition returns for a empty string, None, empty list i.e. [] or {}.
This script will fail if you have "abc,2,3,4,5"
You can also functional loops like
filter(lambda x : x , map(lambda x : int(x) if x else None, a.split(",")))

In Python, how do I check if a string has only alphabets without the built in functions(.islower etc)?

This is my code. it seems to be checking only the first character. I'd like to know how to fix it.
import string
ASCII_LOWERCASE = "abcdefghijklmnopqrstuvwxyz"
ASCII_UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
DECIMAL_DIGITS = "0123456789"
ALPHABETS = ASCII_LOWERCASE + ASCII_UPPERCASE
def is_alpha(string):
for c in "string":
if c in ALPHABETS:
return False
else:
return True
Do not return in every iteration, only return False when you find something that is not in ALPHABET. What about this?
def is_alpha(your_string):
for c in your_string:
if c not in ALPHABETS:
return False
return True
actually its almost half right:
def is_alpha(string):
for c in string:
if not c in ALPHABETS:
return False
return True
short circuiting on False is ok but you need to finish the loop to determine True
There's several issues with your code here.
In your function definition you say
for c in "string"
which means you're checking the characters in the string literal "string".
You'll need to remove the quotes to have it refer to your parameter and actually check the string you're looking at. Further, you should change the name of your parameter and variable to something less ambiguous than string.
As Two-Bit Alchemist points out, you're returning from inside the loop so if the first character is in ALPHABETS then it returns and doesn't execute any more.
Which goes to the final issue. You're returning False if it is an alpha character instead of true. If you change
if c in ALPHABETS:
return False
to
if c not in ALPHABETS:
return False
then delete the else branch and put the return True after the loop it will work as you intend.
Change your function like this:
def is_alpha(string):
for c in string:
if c not in ALPHABETS:
return False
return True
First of all, you had for c in "string": in your code. There you are creating a new string ("string") and looping through the characters in it. Instead, you want to loop through the parameter passed to your function. So remove the double quotes.
Your function returns after first character because you are returning in both cases. Return true only when all characters are in ALPHABETS

See if string contains substring

I was looking for a way to write code that checks whether a certain string is a part of another string. I understand that it is easy to do when we have numbers, but I don't know how to do it with strings.
For example, I have this function
a = is_part("motherland", "land")
I need to know that "land" is a part of the word "motherland" (return True or False). Is it possible to check this?
UPDATE: How can I create a restriction when the second word always has to be in the end of the first one. For example, in case when I check whether "eight" is a part of "eighteen" it returns False because "eight" is not at the end of the first word
This should help:
>>> "land" in "motherland"
True
>>> "banana" in "motherland"
False
Here is a function that determines whether a string target is contained within another string some_string.
def is_part(some_string, target):
return target in some_string
>>> is_part('motherland', 'land')
True
>>> is_part('motherland', 'father')
False
>>> is_part('motherland', '')
True
If you don't like an empty string returning true, change the return statement to
return (target in some_string) if target else False
If, on the other hand, you need to implement it yourself:
def is_part(some_string, target):
if target:
target_len = len(target)
for i in range(len(some_string)):
if some_string[i:i+target_len] == target:
return True
return False

<function>(str1, str2) calling them separately

First off, this IS homework, so I am not expecting any direct answers. I need to take two strings defined by a function (semordnilap(str1, str2)) and I need to see if they are equal when one is reversed. I was wondering if I can call these separately out of the function with semordnilap(str1[0:1) == semordnilap(str2[-1]) I tried this a few ways and I must not be thinking about it correctly, plus of course there is the kicker of trying to do this recursively. Any advise or direction would be helpful.
def semordnilap(str1, str2):
'''
str1: a string
str2: a string
returns: True if str1 and str2 are semordnilap
False otherwise.
'''
if len(str1) != len(str2):
return False
if len(str1) <= 1 or len(str2) <= 1:
return False
if semordnilap(str1[0]) != semordnilap(str2[-1]):
return False
else:
return True
This is what I have so far, getting error of TypeError: semordnilap() takes exactly 2 arguments (1 given)
Given two strings str1 and str2, the easiest way to compare if one is equal to the reverse of the other is by using slicing:
str1 = 'racecar'
str2 = 'racecar'
str1 == str2[::-1]
Out[57]: True
Which is really just checking if str1 is a palindrome (i.e. a reverse of itself).
If you really want to use recursion, you also want to be using slicing: check if str1[0] == str2[-1], and then recursively call your function on str1[1:] and str2[:-1].
The [::-1] syntax is extended slicing syntax, which is valid for strings as well as lists and other sequences.
To reverse a string you use 'this is a string'[::-1].
[::-1] Is slice notation which says include everything from the start to the end of the string but do it in reverse.
'abcdefghijk'[6:1:-2] outputs 'gec' because it goes from the 6th index (starting with 0) up to but not including the first index, in reverse steps of 2.
Read up more on slice notation:Explain Python's slice notation, http://docs.python.org/2.3/whatsnew/section-slices.html
def semordnilap(str1, str2):
if str1 == str2[::-1]: return True
else: return False
One way to do it recursively:
def semordnilap(str1, str2):
if not (len(str1) or len(str2)): return True
if not (len(str1) and len(str2)): return False
if str1[0] != str2[-1]: return False
return semordnilap(str1[1:], str2[:-1])
The first line checks if both strings are empty (0 evaluates to False, any other number is True). len(str1) returns the length as an integer.
Then it checks if only one of the strings is empty in which case they are not equal.
Then it checks if the first letter is the same as the last letter.
Then it repeats the process with the each string (minus the first letter of str1 and minus the last letter of str2). It goes until one of the base cases is reached. The base case is what is returned. So it will only return True when then first letter was equal to the last letter each round until both strings ran out of characters at the same time.

Categories

Resources