Testing for an item in lists - Python 3 - list

As part of a school project we are creating a trouble shooting program. I have come across a problem that I cannot solve:
begin=['physical','Physical','Software','software',]
answer=input()
if answer in begin[2:3]:
print("k")
software()
if answer in begin[0:1]:
print("hmm")
physical()
When I try to input software/Software no output is created. Can anybody see a hole in my code as it is?

In Python, slice end values are exclusive. You are slicing a smaller list than you think you are:
>>> begin=['physical','Physical','Software','software',]
>>> begin[2:3]
['Software']
>>> begin[0:1]
['physical']
Use begin[2:4] and begin[0:2] or even begin[2:] and begin[:2] to get all elements from the 3rd to the end, and from the start until the 2nd (inclusive):
>>> begin[2:]
['Software', 'software']
>>> begin[2:4]
['Software', 'software']
>>> begin[:2]
['physical', 'Physical']
>>> begin[0:2]
['physical', 'Physical']
Better yet, use str.lower() to limit the number of inputs you need to provide:
if answer.lower() == 'software':
With only one string to test, you can now put your functions in a dictionary; this gives you the option to list the various valid answers too:
options = {'software': software, 'physical': physical}
while True:
answer = input('Please enter one of the following options: {}\n'.format(
', '.join(options))
answer = answer.lower()
if answer in options:
options[answer]()
break
else:
print("Sorry, {} is not a valid option, try again".format(answer))

Your list slicing is wrong, Try the following script.
begin=['physical','Physical','Software','software',]
answer=input()
if answer in begin[2:4]:
print("k")
software()
if answer in begin[0:2]:
print("hmm")
physical()

Related

Exact match of string in pandas python

I have a column in data frame which ex df:
A
0 Good to 1. Good communication EI : tathagata.kar#ae.com
1 SAP ECC Project System EI: ram.vaddadi#ae.com
2 EI : ravikumar.swarna Role:SSE Minimum Skill
I have a list of of strings
ls=['tathagata.kar#ae.com','a.kar#ae.com']
Now if i want to filter out
for i in range(len(ls)):
df1=df[df['A'].str.contains(ls[i])
if len(df1.columns!=0):
print ls[i]
I get the output
tathagata.kar#ae.com
a.kar#ae.com
But I need only tathagata.kar#ae.com
How Can It be achieved?
As you can see I've tried str.contains But I need something for extact match
You could simply use ==
string_a == string_b
It should return True if the two strings are equal. But this does not solve your issue.
Edit 2: You should use len(df1.index) instead of len(df1.columns). Indeed, len(df1.columns) will give you the number of columns, and not the number of rows.
Edit 3: After reading your second post, I've understood your problem. The solution you propose could lead to some errors.
For instance, if you have:
ls=['tathagata.kar#ae.com','a.kar#ae.com', 'tathagata.kar#ae.co']
the first and the third element will match str.contains(r'(?:\s|^|Ei:|EI:|EI-)'+ls[i])
And this is an unwanted behaviour.
You could add a check on the end of the string: str.contains(r'(?:\s|^|Ei:|EI:|EI-)'+ls[i]+r'(?:\s|$)')
Like this:
for i in range(len(ls)):
df1 = df[df['A'].str.contains(r'(?:\s|^|Ei:|EI:|EI-)'+ls[i]+r'(?:\s|$)')]
if len(df1.index != 0):
print (ls[i])
(Remove parenthesis in the "print" if you use python 2.7)
Thanks for the help. But seems like I found a solution that is working as of now.
Must use str.contains(r'(?:\s|^|Ei:|EI:|EI-)'+ls[i])
This seems to solve the problem.
Although thanks to #IsaacDj for his help.
Why not just use:
df1 = df[df['A'].[str.match][1](ls[i])
It's the equivalent of regex match.

Use list to generate lowercase letter and number in python

I am trying to use a list such as:
[(1,4),(2,2)]
To get:
[(a,4),(b,2)]
I am trying to use 'string.ascii_lowercase' how would I accomplish this in Python3, this is for a coding challenge to get the least characters possible.
Thanks for any help!
I'm not going to solve it for you, but I'd suggest you look into the chr and ord functions. Note that the ASCII code for "a" is 97, so to convert 1 to "a" you would have to add 96 to it.
I would suggest you to follow the suggestion given by B.Eckles above as you would learn better and probably find a shorter (character-wise) solution.
However, if you want to stick with using string.ascii_lowercase, the code snippet below could be useful to start from:
import string
a = [(1,4),(2,2)]
b = []
for (first, second) in a:
b.append(
(string.ascii_lowercase[(first-1) % len(string.ascii_lowercase)],
second))
print b
In this case, the printed solution would be:
[('a', 4), ('b', 2)]
I have inserted the module (i.e. % len(string.ascii_lowercase)) to avoid out-of-bound accesses. Just be careful that the value 0 would produce 'z' in this way.
Hope it helps!

Partial match in a list, from a user input

Trying to get a partial match in a list, from a user input.
I am trying to make a simple diagnostic program. The user inputs their ailment and the program will output a suggested treatment.
print("What is wrong with you?")
answer=input()
answer=answer.lower()
problem=""
heat=["temperature","hot"]
cold=["freezing","cold"]
if answer in heat:
problem="heat"
if answer in cold:
problem="cold"
print("you have a problem with",problem)
I can get it to pick an exact match from the list but I want it to find partial matches from my input. For example if the user types they are "too hot".
Try the code below. The key is the split() method.
answer = input('What is wrong with you?')
answer = answer.lower()
heat = ['temperature', 'hot']
cold = ['freezing', 'cold']
for word in answer.split():
if word in heat:
problem = 'heat'
if word in cold:
problem = 'cold'
print('you have a problem with', problem)
I would recommend you use something like this which might be a bit more "pythonic"
answer = input()
cold = ["freezing", "cold"]
if any(answer in c for c in cold):
problem = "cold"

How to change/modify strings different in a list

I don't know if this question has been asked before, but it seems that I can't find the function that I am looking for. I want to add two different string to different strings in a list. Something like this:
old_list: ['spider','cat','iron','super','bat']
old_list: ['spiderman','catwoman','ironman','superwoman','batman']
So I want some kind of function that changes the strings by adding 'man' or 'woman' without making a new list. I think/know it can be done with some kind of for-loop but can't seem to find a easy way of doing it. And I am sorry if this question has been asked before, but I can't really find an answer to this specific function.
Slice-assign back into the list.
>>> ['{}{}'.format(pref, suff) for (pref, suff) in zip(old_list, itertools.cycle(('man', 'woman')))]
['spiderman', 'catwoman', 'ironman', 'superwoman', 'batman']
>>> id(old_list)
43518144
>>> old_list[:] = ['{}{}'.format(pref, suff) for (pref, suff) in zip(old_list, itertools.cycle(('man', 'woman')))]
>>> id(old_list)
43518144
>>> old_list
['spiderman', 'catwoman', 'ironman', 'superwoman', 'batman']
Just for the sake of a simpler answer, I will post this one:
for i in range(len(old_list)):
old_list[i] += suffixes[i%len(suffixes)]
Note you can have any number of suffixes.

How to obtain all solutions for cos(x)*cosh(x) == 1 in Sympy?

Following is the best I can get.
map(lambda n: nsolve(cos(x)*cosh(x)-1,x,3.14/2+3.14*n),range(9))
[mpf('0.0039941152964418809'),
mpf('4.730040744862704'),
mpf('7.8532046240958376'),
mpf('10.995607838001671'),
mpf('14.137165491257464'),
mpf('17.278759657399481'),
mpf('20.420352245626061'),
mpf('23.561944902040455'),
mpf('26.703537555508186')]
If you change range(9) to range(10), sympy will return an error.
ValueError: Could not find root within given tolerance. (1.59798e-17 > 2.1684e-1
9)
Try another starting point or tweak arguments.
I have asked this in the Mathematica site, Mathematica seems can provide the solutions quite accurate and fast. Check this out: how-to-obtain-all-solutions-for-cosx-coshx-1
This is a nice example of using an intelligent initial guess. If you just provide a tolerance you can find the additional solution:
>>> len([nsolve(cos(x)*cosh(x)-1,x,3.14/2+3.14*n,tol=1e-12) for n in range(10)])
10
Note, however, that the function is very steep in the region of the roots and it is unlikely that you will every end up with an x value that will make the function value small. If you know that your initial guesses leads to a root and not a discontinuity, you can safely use the verify=False to skip the verification of the solution (and verify it yourself, perhaps by taking the slope into account). I always feel safer using the bisect method, however, in these cases:
>>> f
cos(x)*cosh(x) - 1
>>> bounds = lambda i: (3.14*i, 3.14*(i+1))
>>> root = lambda i: nsolve(f, bounds(i), solver='bisect', verify=False)
>>> root(0)
mpf('0.0')
>>> root(99)
mpf('312.58846903218443')
>>> root(100)
mpf('315.73006168577422')
You can see that the function at this point is very large, but if we normalize by the derivative of the function the answer looks better:
>>> ans = _
>>> f.subs(x, ans).n(2)
2.3e+122
>>> (f/f.diff(x)).subs(x, ans).n(2)
-3.4e-15
Note: currently, it will not work to pass a normalized function to nsolve so it can be used in the solving process: nsolve only works with the numerator of the function you pass.