How to write a function to compare two strings alphabetically? - python

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.

Related

How to find if given string is a subsequence of another given string recursively without imports?

Assignment:
Write a recursive function named is_subsequence that takes two
string parameters and returns True if the first string is a
subsequence of the second string, but returns False otherwise. We say
that string A is a subsequence of string B if you can derive A by
deleting zero or more letters from B without changing the order of the
remaining letters. You can assume that neither string contains
upper-case letters.
You may use default arguments and/or helper functions.
Your recursive function must not:
use imports.
use any loops use any variables declared outside of the function.
use any mutable default arguments.
What I have so far (must use this format):
def is_subsequence(strA, strB = None):
if strB == None:
strB = []
print(is_subsequence("dog", "dodger"))
My problem:
I can't figure out how to recursively edit the string the way the assignment says by removing letters. (strB.replace("e","") doesn't work).
I dont know if this is allowed based on the instructions but i added an index param and was able to come up with this. (Snippet is Python)
def is_subsequence(strA, strB, index=0):
"""
Function that determines if string A is a subsequence of string B
:param strA: String to compare subsets to (strings are immutable)
:param strB: Parent string to make subsets of (strings are immutable)
:param index: number of combinations tested
:return: True if a subsequence is found, False if index reaches maximum with none found
"""
binary = '{:0{leng}b}'.format(index, leng=len(strB))
if index > 2**len(strB)-1: #If past maximum return False
return False
def makesub(sub="", pos=0):
"""
Function that builds up the current subsequence being tested by using binary to choose letters
:param sub: The currently selected letters
:param pos: Position in binary string to compare
:return: completed subsequence for comparing to strA
"""
if pos > len(binary)-1: #If pos is passed the length of our binary number return the created subsequence
return sub
if binary[pos] == "1": #If the pos in binary is a 1, add the letter to our sub. If it is 0 do nothing.
sub = sub + strB[pos]
return makesub(sub, pos + 1) #increment pos and try again or return what the call returned
if makesub() == strA: #If the returned sub matches strA we found a matching subsequence, return True
return True
return is_subsequence(strA, strB, index + 1) #increment index and try again or return what the call returned
print(is_subsequence("dog", "dodger"))

Assigning multiple values to a single int or float or string variable in python. Is it possible?

Recently I encountered someone's code along the lines of:
b = {
'b': "b" or []
}
When I do a print(b) I get {'b': 'b'}. It got me questioning when will b ever be []? Or is it saying b is both "b" and []?
But if that is the case:
a = (1 or 2)
print(a == 1)
print(a == 2)
Why does print(a == 1) results in True but print(a==2) results in False?
This leads me to a final question, is it possible for a variable of type int or float or string to hold multiple values at the same time? ie, a is both 1 and 2 provided that it is not a list or dictionary?
No, you can't assign multiple values to a single variable.
The expression x or y returns y if x is false, or x if not.
A string only evaluates false if it's empty. Your string "b" is not empty, so it will never be false. Thus there's no way for that expression "b" or [] to equal [], it will always be "b".
Not, it is not possible.
What you have done is assign to a the value of the expression (1 or 2); that is, the result of or-ing 1 and 2.
a will never be 2. (1 or 2) will always evaluate to 1 because python evaluates these logical expressions left-to-right.
If the left-most one is not False, empty list, None, etc then it will assign that value to a and stop reading. The interpreter only looks at the second value if the first one is "no good".
is it possible for a variable of type int or float or string to hold multiple values at the same time?
Maybe in Quantum Computing, but certainly not in normal programming.
You're misunderstanding what the posted syntax does. When you assign a value using that expression, it assigns the first "truthy" value it comes across in left-to-right order. Any remaining value candidates after that first truthy one are discarded/ignored.
As it stands, the example you gave is pretty redundant - non-empty strings are "truthy", and since it's a literal "b", the empty list never even gets considered. That code is fundamentally equivalent to:
b = {
'b': "b"
}
With respect to your code snippets, the ored expressions are evaluated when they are assigned:
Since x or y returns x if x evaluates to True, else returns y,
the values of b and a from the examples are:
b = {'b': 'b'}
a = 1
and that is, what the print function returns.
Concerning the final question: It is not possible that a is 1 and 2 at the same time, but you can create a new type, so that a equals 1 and 2 at the same time:
class multiple_values:
def __init__(self, data):
self.data = set(data)
def __eq__(self, value):
return value in self.data
a = multiple_values([1, 2])
A list of 'valid' values is given to initialise a, but a itself is not a list.
a == 1 as well as a == 2 evaluate to True, while e.g. a == 3 evaluates to False.
But please note, that the type definition for multiple_values would need to be expanded in order to be useful for more than just an equality test.
Also, you asked for an int, float or string to have multiple values. a is not an int - it only 'behaves' like one in this limited example.

Python's slice notation when a two-word start with same string and it should return True

I need to check whether a two-word string start with same string (letter) should return True. I am not sure which slicing method apply here. I gone through the various post here but could not find the required one. Based on my code, the result always give 'none'.
def word_checker(name):
if name[0] =='a' and name[::1] == 'a':
return True
print(word_checker('abc adgh'))
You need to split the string on spaces and check the first letter of each split:
def word_checker(name):
first, second = name.split()
return first[0] == 'a' and second[0] == 'a'
print(word_checker('abc adgh'))
Output
True
But the previous code will only return True if both words start with 'a', if both must start with the same letter, you can do it like this:
def word_checker(name):
first, second = name.split()
return first[0] == second[0]
print(word_checker('abc adgh'))
print(word_checker('bar barfoo'))
print(word_checker('bar foo'))
Output
True
True
False
'abc adgh'[::1] will simply return the entire string. See Understanding Python's slice notation for more details (list slicing is similar to string slicing).
Instead, you need to split by whitespace, e.g. using str.split. A functional method can use map with operator.itemgetter:
from operator import itemgetter
def word_checker(name):
a, b = map(itemgetter(0), name.split())
return a == b
print(word_checker('abc adgh')) # True
print(word_checker('abc bdgh')) # False

Python: can a function return a string?

I am making a recursive function that slices string until it is empty. When it is empty it alternatively selects the characters and is supposed to print or return the value. In this case I am expecting my function to return two words 'Hello' and 'World'. Maybe I have got it all wrong but what I don't understand is that my function doesn't let me print or return string. I am not asking for help but I'd like some explanation :) thanks
def lsubstr(x):
a= ''
b= ''
if x == '':
return ''
else:
a = a + x[0:]
b = b + x[1:]
lsubstr(x[2:])
#print (a,b)
return a and b
lsubstr('hweolrllod')
so I changed my code to this:
def lsubstr(x):
if len(x) <1:
return x
else:
return (lsubstr(x[2:])+str(x[0]),lsubstr(x[2:])+str(x[1]))
lsubstr('hweolrllod')
and what I am trying to make is a tuple which will store 2 pairs of characters and concatenate the next ones,
the error I get is
TypeError: Can't convert 'tuple' object to str implicitly
what exactly is going wrong, I have checked in visualization, it has trouble in concatenating.
The and keyword is a boolean operator, which means it compares two values, and returns one of the values. I think you want to return a tuple instead, like this:
...
return (a, b)
And then you can access the values using the indexing operator like this:
a = lsubstr( ... )
a[0]
a[1]
Or:
word1, word2 = lsubstr( ... )

compare two python strings that contain numbers [duplicate]

This question already has answers here:
How do I compare version numbers in Python?
(16 answers)
Closed 5 months ago.
UPDATE: I should have specified this sooner, but not all of the names are simply floats. For example, some of them are "prefixed" with "YT". So for example" YT1.1. so, you have the same problem YT1.9 < YT1.11 should be true. I'm really surprised that the string comparison fails....
hello,
this should be a pretty simple question but I can't seem to find the answer. I'd like to sort a bunch of XL worksheets by name. Each of the names are numbers but in the same way that textbook "sections" are numbered, meaning section 4.11 comes after 4.10 which both come after 4.9 and 4.1. I thought simply comparing these numbers as string would do but I get the following:
>>> s1 = '4.11'
>>> s2 = '4.2'
>>> s1> s2
False
>>> n1 = 4.11
>>> n2 = 4.2
>>> n1 > n2
False
how can I compare these two values such that 4.11 is greater than 4.2?
Convert the names to tuples of integers and compare the tuples:
def splittedname(s):
return tuple(int(x) for x in s.split('.'))
splittedname(s1) > splittedname(s2)
Update: Since your names apparently can contain other characters than digits, you'll need to check for ValueError and leave any values that can't be converted to ints unchanged:
import re
def tryint(x):
try:
return int(x)
except ValueError:
return x
def splittedname(s):
return tuple(tryint(x) for x in re.split('([0-9]+)', s))
To sort a list of names, use splittedname as a key function to sorted:
>>> names = ['YT4.11', '4.3', 'YT4.2', '4.10', 'PT2.19', 'PT2.9']
>>> sorted(names, key=splittedname)
['4.3', '4.10', 'PT2.9', 'PT2.19', 'YT4.2', 'YT4.11']
This is not a built-in method, but it ought to work:
>>> def lt(num1, num2):
... for a, b in zip(num1.split('.'), num2.split('.')):
... if int(a) < int(b):
... return True
... if int(a) > int(b):
... return False
... return False
...
... lt('4.2', '4.11')
0: True
That can be cleaned up, but it gives you the gist.
What you're looking for is called "natural sorting". That is opposed to "lexicographical sorting". There are several recipes out there that do this, since the exact output of what you want is implementation specific. A quick google search yields this (note* this is not my code, nor have I tested it):
import re
def tryint(s):
try:
return int(s)
except:
return s
def alphanum_key(s):
""" Turn a string into a list of string and number chunks.
"z23a" -> ["z", 23, "a"]
"""
return [ tryint(c) for c in re.split('([0-9]+)', s) ]
def sort_nicely(l):
""" Sort the given list in the way that humans expect.
"""
l.sort(key=alphanum_key)
http://nedbatchelder.com/blog/200712.html#e20071211T054956
use s1.split(".") to create a list of the items before and after the decimal then sort the list of lists, example:
import random
sheets = list([str(x), str(y)] for x in xrange(1, 5) for y in xrange(0,99))
print sheets
#sheets in order
random.shuffle(sheets)
print sheets
#sheets out of order
sheets.sort()
print sheets
#sheets back in order
So, you implementation might be:
#assume input sheets is a list of the worksheet names
sheets = list(x.split(".") for x in input_sheets)
sheets.sort()
If you know they are real numbers [*] , simply:
>>> float(s1) > float(s2)
True
[*] Otherwise, be ready to handle a raised ValueError.

Categories