Compare strings with different operators in python - python

I'd like to compare two strings in a function with the comparison/membership operators as argument.
string1 = "guybrush"
string2 = "guybrush threepwood"
def compare(operator):
print(string1 operator string2)
compare(==) should print False and
compare(in) should print True
It's obviously not working like that. Could I assign variables to the operators, or how would I solve that?

You can't pass in operators directly, you need a function like so:
from operator import eq
string1 = "guybrush"
string2 = "guybrush threepwood"
def compare(op):
print(op(string1, string2))
compare(eq)
>>>False
The in operator is a little more tricky, since operator doesn't have an in operator but does have a contains
operator.contains(a, b) is the same as b in a, but this won't work in your case since the order of the strings are set. In this case you can just define your own function:
def my_in(a, b): return a in b
compare(my_in)
>>>True

Related

How to write a function to compare two strings alphabetically?

If a="formula" and b="formulab" are two strings, how can the function compare which string comes after the other and return a true or false value?
We know string b will come after, but how to determine that using the function?
def alphabet_order(a,b):
if len(a) > len(b):
return True
else:
return False
I am getting the length of the strings, but how can I sort the strings lexicographically and compare them?
Python compares strings lexicographically based on their order in the ascii table for alphabet (where each letter is essentially assigned a value).
Here is a link to the numeric order: https://www.asciitable.com/
So you now have two options:
compare by length (using len()).
compare by value.
Here is an example of the value comparison:
a = 'hello'
b = 'world'
if a > b:
print('a > b')
else :
print('a < b')
which returns this:
a < b
because "hello comes" before "world" in that ordering.
You can wrap the above into a function.

In python by what logic we can add "for" loop with another statement as it is done in the mentioned example?

In the below function, while loop condition has 2 statements/expressions "x in my_string" and "for x in brackets", by what logic both can be mentioned together?
def check(my_string):
brackets = ['()', '{}', '[]']
while any(x in my_string for x in brackets):# How can 2 statements be mentioned
for br in brackets:
my_string = my_string.replace(br, '')
return not my_string
This is a language construct known as a generator expression. Read more here: https://djangostars.com/blog/list-comprehensions-and-generator-expressions/
the for x in brackets parts is indeed a comprehension,
but the x in my_string part is just the in operator. like 'bcd' in 'abcdefg' or 2 in [1,2,3], the result of which is Boolean.
any is then used to check if at least one of those Booleans is True.

Is it possible to use isalpha() on a math string, and still return True in python?

For example, I want to return True if the string is all lowercase, and only contains alphabetical characters (with the exception of math operators).
For example:
'x' is True, 'X' is False, 'x+y' is True # here's where it doesn't work.
My current condition is:
if not str.islower() or not str.isalpha():
return False
When I do x+y, it is all lower, but the string is not alpha. I want a way to somehow ignore the standard math operators: +, -, * since this is a math expression. Is this possible without much code?
[...] I want to return True if the string is all lowercase, and only contains alphabetical characters (with the exception of math operators).
In my opinion the simplest solution would simply be to make your own function:
def is_valid_string(string, operators):
string = ''.join([c for c in string if c not in operators])
return all(c.isalpha() and c.lower() for c in string)
And it could be used like so:
if is_valid_string(str):
# code
In this way, you can easily customize which operators are ignored and which are not.
You can use regex and turn your code to:
import re
p = re.compile('^[a-z+*/-]+$')
return p.match(str)
import string
comp = string.ascii_lowercase + "+-/*"
Then your valid replacement is:
if not all([False for char in str if char not in comp]):
return False
Uses a set in for each char, and only builds a list on failures (fast for good matches).
As a function:
def valid(string):
comp = string.ascii_lowercase + "+-/*"
return all([False for char in str if char not in comp])
You can use regex:
import re
return bool(re.fullmatch(r'[a-z*/+-]+', 'x+y'))

Combining several logical conditions from a list

I'm trying to do something that is seemingly simple: I have a list whose elements are logical expressions and I want a function that combines them into one logical expression, using a chosen logical operator (& or | is enough).
The following code does this, however, shouldn't there be a better way of doing this? It doesn't feel very Python-esque to me (main problem I see is the use of "exec", does anyone have an idea how to do it without?):
def CombineLogicalExpressions(listofexpressions,operator,outputvariableName):
''' return a condition combined from individual ones
listofexpressions = ["a == 1", "b == 2"]
operator = "and"
outputvariableName = 'myVar'
'''
#generate list from which the condition can be read:
logicalconditions = []
for expression in listofexpressions:
logicalconditions.append(expression)
logicalconditions.append(' ' + str(operator) + ' ')
del logicalconditions[-1] # delete the final operator
#create string that holds the full expression
condition = ''
for a in logicalconditions:
condition = condition + a
condition = 'FinalExpression = (' + condition + ')'
return condition
FinalExpression = False
a = 1
b = 2
condition = CombineLogicalExpressions(['a == 1', 'b == 2'] ,
'and', 'FinalExpression')
#set FinalBooleanQueryResult to the outcome of executing condition:
exec condition
print FinalExpression
You are probably wondering why I would have the logical conditions as strings. This is a simplification in the code above. In reality, I have a container object 'someContainer' and it has a method '.contains(string)' which will return a query which can be used to slice the container and give all entries whose key contains 'string':
#returns sliced someContainer with keys matching 'string'
someContainer[someContainer.contains(string)]
Now I would like to extend the functionality of 'contain()' to be able to supply a list of strings:
#returns sliced someContainer with keys matching all strings in 'listofkeywords'
containsMultiple(someContainer, listofkeywords)
I hope this is not too long and specific to put people off! I have tried searching for answers, but to my surprise couldn't find anything.
You could easily use the any() or all() builtins for this:
class Container(object):
def __init__(self, items):
self.items = items
def contains(self, s):
return s in self.items
def contains_any(some_container, items):
return any((some_container.contains(i) for i in items))
def contains_all(some_container, items):
return all((some_container.contains(i) for i in items))
c = Container(['foo', 'bar'])
print contains_any(c, ['foo', 'qux'])
print contains_all(c, ['foo', 'qux'])
print contains_all(c, ['foo', 'bar'])
Output:
True
False
True
The (some_container.contains(i) for i in items) inside the any() or all() calls is a so called generator expression. It's similar to a list comprehension, but it's lazy, possibly saving you plenty of calls to Container.contains().
In fact I found a very nice and neat solution for my problem, using the "reduce" function and the operator module. The operator module turns a binary operator into a function that takes two arguments, like:
operator.and_(A,B) equivalent to: (A and B).
Reduce will apply a function of two arguments cumulatively to a list of arguments, i.e.
reduce(function,[A,B,C]) equivalent to: function( A, function(B,C) )
With this I'll give the code which is solving the original simplified problem I gave below. Note that this, in particular, also works perfectly for the containers I am actually interested in:
def CombineLogicalExpressionsBetter(listofexpressions,operatorname):
'''
use as:
CombineLogicalExpressionsBetter([a == 1, b == 2, c == 'z'], 'and')
'''
import operator
#make it easier for users to enter operators:
if operatorname in ('and','and_') :
operatorname = operator.and_
elif operatorname in ('or','or_'):
operatorname = operator.or_
elif operatorname in ('not','not_'):
operatorname = operator.not_
else:
raise Exception("Please enter a valid operator:
'and', 'or', 'not' ... I got: " + operatorname)
#combine expression:
totalexpression = reduce(operatorname, (expression for expression in
listofexpressions))
return totalexpression

Can you compare strings in python like in Java with .equals?

Can you compare strings in Python in any other way apart from ==?
Is there anything like .equals in Java?
There are two ways to do this. The first is to use the operator module, which contains functions for all of the mathematical operators:
>>> from operator import eq
>>> x = "a"
>>> y = "a"
>>> eq(x, y)
True
>>> y = "b"
>>> eq(x, y)
False
>>>
The other is to use the __eq__ method of a string, which is called when you use ==:
>>> x = "a"
>>> y = "a"
>>> x.__eq__(y)
True
>>> y = "b"
>>> x.__eq__(y)
False
>>>
You could do:
import operator
a = "string1"
b = "string2"
print operator.eq(a, b)
This is similar to Java in that you're not using an explicit operator.
However in Java you're using a method call on the String class (i.e., myString.equals(otherString)) but in Python eq is just a function which you import from a module called operator (see operator.eq in the documentation).
According to the docs:
eq(a, b) is equivalent to a == b
So == is just like .equals in Java (except it works when the left side is null).
The equivalent of Java's == operator is the is operator, as in:
if a is b
What is the need for using other than '==' as python strings are immutable and memoized by default?
As pointed in other answers you can use 'is' for reference(id) comparison.
In Java, .equals() is used instead of ==, which checks if they are the same object, not the same value. .equals() is used for comparing the actual values of 2 strings.
However, in Python, "==" by default checks if they have the same value so it is better to use in general.
As other solutions pointed out, you can also __eq__ as another way to get the same result.

Categories