Trouble with Palindrome function in python - python

I'm having trouble in an online course for python, specifically a palindrome problem These are the instructions, but the function must be case-insensitive and not see spaces. I think the issue is in my return blocks or my flow. I think I need to use the lower function, but I'm honestly not sure.
def student_func(x):
for string in x:
x.lower()
y = x.replace(" ", "")
if y[::-1]==y:
return True
else:
return False

You actually have two separate problems in your code—and you're right that one of them is with lower and the other is with the return flow.
First, x.lower() doesn't modify x in-place. In fact, strings are immutable; nothing modifies them in-place. If you look up the interactive help or the online docs, it says:
Return a copy of the string with all the cased characters [4] converted to lowercase.
So, you need to do the same thing with lower that you do with replace: assign the result to a variable, and use that:
y = x.lower()
z = y.replace(" ", "")
Or you can reuse the same variable:
x = x.lower()
… or chain the two calls together:
y = x.lower().replace(" ", "")
As a side note, unless you're using Python 2, you should consider whether you want casefold instead of lower. For English it makes no difference, but for other languages it can.
Meanwhile, you're doing for string in x:, but then ignoring string.
If x is just a single word, you don't want to loop over it at all.
If x is a list of words, then the for string in x: is correct, but then you have to use string inside the loop, not x. Plus, you can't just return True or return False—that will exit the function as soon as you test the first word, meaning the rest of them never get tested. I'm not sure whether you want to return True if there are any pallidromes, or if they're all palindromes, or if you want to return a list of booleans instead of a single one, or what, but you can't just return the first one.
It would probably be a lot clearer if you used better names, like words instead of x and word instead of string.
Anyway, I can't tell you the right way to fix this since I don't know what you're trying to do, but hopefully this explains enough that you can fix it yourself.

Giving away the solution defeats the purpose of the exercise
your approach is more or less correct.
convert string to a standard case
remove whitespace
check if reverse of the string is equal to the original string
The error lies in how you are using the python API.
check what each of the functions do, and what they return.
a good idea is to run help(function) to see what the function's documentation has to say about it.
try help(x.lower) (note: not help(x.lower())) and see what the return value is.

Related

While loops where only conditions are executed? [duplicate]

This question already has answers here:
Remove all occurrences of a value from a list?
(26 answers)
Closed 2 years ago.
So I want to execute only while loop statements, without putting anything inside them. For example, I have an array arr from which I have to remove multiple occurrences of some element. The instant the condition statement returns an error, while loop should end.
arr=[1,2,4,2,4,2,2]
This removes only one 2:
arr.remove(2)
I need to run this as long as it does not return error. (C++ has a semicolon put after while to do this).
I want something like this
while(arr.remove(2));
Three things.
First, it's not considered good practice in Python – it's not "pythonic" – to use an expression for its side effects. This is why, for example, the Python assignment operator is not itself an expression. (Although you can do something like a = b = 1 to set multiple variables to the same value, that statement doesn't break down as a = (b = 1); any such attempt to use an assignment statement as a value is a syntax error.)
Second, modifying data in place is also discouraged; it's usually better to make a copy and make the changes as the copy is constructed.
Third, even if this were a good way to do things, it wouldn't work in this case. When the remove method succeeds, it returns None, which is not truthy, so your loop exits immediately. On the other hand, when it fails, instead of returning a false value, it throws an exception, which will abort your whole program instead of just the loop, unless you wrap it in a try block.
So the list comprehension probably is the best solution here.
The way you are looking to solve this does not yield the results you are looking for. Since you are looking to create a new list, you are not going to want to use the remove function as per #Matthias comment. The idiomatic way to do it would be something along the lines of this:
arr=[1,2,4,2,4,2,2]
arr = [x if x != 2 for x in arr]
So I want to execute only while loop statements, without putting anything inside them.
That's really not necessary. Don't try to copy other language's syntax in Python. Different languages are designed with different objectives and hence, they have different syntax (or grammar of the language). Python has a different way of doing things than C++.
If you want to focus on the effectiveness of the program, then that's the different story. See this for more information on this.
Unfortunately, remove doesn't return anything (it returns None). So, you can't have anything that would look neat and clean without putting anything inside while.
Pythonic way to remove all occurrence of a element from list:
list(filter((2).__ne__, arr))
Or
arr = [x for x in arr if x != 2]
Or
while 2 in arr:
arr.remove(2)
you can use:
arr = [1,2,4,2,4,2,2]
try:
while arr.pop(arr.index(2)):
pass
except ValueError:
pass
print(arr)
#[1, 4, 4]
I am assuming you want to remove all occurrences of an element. This link might help you.
click here

How to search through each letter in a dictionary and use it properly

If I were to take a dictionary, such as
living_beings= {"Reptile":"Snake","mammal":"whale", "Other":"bird"}
and wished to search for individual characters (such as "a") (e.g.
for i in living_beings:
if "a" in living_beings:
print("a is here")
would there be an efficient- runs fastest- method of doing this?
The input is simply searching as outlined above (although my approach didn't work).
My (failed) code goes as follows:
animals=[]
for row in reader: #'reader' is simply what was in the dictionary
animals.append(row) #I tried to turn it into a list to sort it that way
for i in range(1, len(animals)):
r= animals[i]
for i in r:
if i== "a": #My attempt to find "a". This is obviously False as i= one of the strings in
k=i.replace("'","/") #this is my attempt at the further bit, for a bit of context
test= animals.append(k)
print(test)
In case you were wondering,
The next step would be to insert a character- "/"- before that letter (in this case "a"), although this is a slightly different problem and so not linked with my question and is simply there to give a greater understanding of the problem.
EDIT
I have found another error relating to dictionary. If the dictionary features an apostrophe (') the output is affected as it prints that particular word in quotes ("") rather that the normal apostrophes. EXAMPLE: living_beings= {"Reptile":"Snake's","mammal":"whale", "Other":"bird"} and if you use the following code (which I need to):
new= []
for i in living_beings:
r=living_beings[i]
new.append(r)
then the output is "snake's", 'whale', 'bird' (Note the difference between the first and other outputs). So My question is: How to stop the apostrophes affecting output.
My approach would be to use dict comprehension to map over the dictionary and replace every occurence of 'a' by '/a'.
I don't think there are significant performance improvements that can be done from there. You algorithm will be linear with regard to the total number of characters in the keys and items of the dict as you need to traverse the whole dictionary whatever the input.
living_beings= {"Reptile":"Snake","mammal":"whale", "Other":"bird"}
new_dict = {
kind.replace('a', '/a'): animal.replace('a', '/a') for kind, animal in living_beings.items()
}
# new_dict: {"Reptile":"Sn/ake","m/amm/al":"wh/ale", "Other":"bird"}
You could maybe optimize with a more convoluted solution that loops through the dict to mutate it instead of creating a new one, but in general I recommend not trying to do such things in Python. Just write good code, with good practices, and let Python do the optimization under the hood. After all this is what the Zen of Python tells us: Simple is better than complex.
This can be done quite efficiently using a regular expression match, e.g.:
import re
re_containsA = re.compile(r'.*a.*')
for key, word in worddict.items():
if re_containsA.match(word):
print(key)
The re.match object can then be used to find the location of the matched text.

Giant set of strings leads to memory error - alternative?

I'm trying to create a really huge list of incrementing 9 digits numbers (worst case). My plan is to have something like this:
['000000001', '000000002' , ..............,'999999999']
I already wrote the code. However, as soon as I run the code, my console prints "Memory Error" message.
Here is my current code:
HUGE_LIST = [''.join(i) for i in product('012345678', repeat = 9)
I know this might not be the best code to produce the list. Thus, can someone help me find a better way to solve this memory issue?
I'm planning to use HUGE_LIST for comparison with user input.
Example: a user enters '12345678' as input, then I want my code to assert that input with the HUGE_LIST.
The best way to solve an issue like this is to avoid a memory-intensive algorithm entirely. In this case, since your goal is to test whether a particular string is in the list, just write a function that checks whether the string satisfies the criteria to be in the list. For example, if your list contains all sequences of 9 digits, then your function just has to check whether a given input is a sequence of 9 digits.
def check(string):
return len(string) == 9 and all(c.isdigit() for c in string)
(in practice, give it a better name than check). Or if you want all sequences of 9 digits in which none of them is a 9, as your current code defining HUGE_LIST suggests, you could write
def check(string):
return len(string) == 9 and all(c.isdigit() and c != '9' for c in string)
Or so on.
If you can't write an algorithm to decide whether a string (or whatever) is in the list or not, the next best thing is to make a generator that will produce the values one at a time. If you already have a list comprehension, like
HUGE_LIST = [<something> for <variable> in <expression>]
then you can turn that into a generator by replacing the square brackets with parentheses:
HUGE_GENERATOR = (<something> for <variable> in <expression>)
Then you can test for membership using string in HUGE_GENERATOR. Note that after doing so, HUGE_GENERATOR will be (at least partially) consumed, so you can't use it for another membership test; you will have to recreate it if you want to test again.

Why am I getting a syntax error for this conditional statement?

I've recently been practicing using map() in Python 3.5.2, and when I tried to run the module it said the comma separating the function and the iterable was a SyntaxError. Here's the code:
eng_swe = {"merry":"god", "christmas":"jul", "and":"och", "happy":"gott",
"new":"nytt", "year":"år"}
def map_translate(l):
"""Translates English words into Swedish using the dictionary above."""
return list(map(lambda x: eng_swe[x] if x in eng_swe.keys(), l))
I noticed that if I eliminate the conditional statement like this:
return list(map(lambda x: eng_swe[x], l))
it works fine, but it sacrifices the ability to avoid attempting to add items to the list that aren't in the dictionary. Interestingly enough, there also weren't any problems when I tried using a conditional statement with reduce(), as shown here:
from functools import reduce
def reduce_max_in_list(l):
"""Returns maximum integer in list using the 'reduce' function."""
return reduce(lambda x, y: x if x > y else y, l)
Yes, I know I could do the exact same thing more cleanly and easily with a list comprehension, but I consider it worth my time to at least learn how to use map() correctly, even if I end up never using it again.
You're getting the SyntaxError because you're using a conditional expression without supplying the else clause which is mandatory.
The grammar for conditional expressions (i.e if statements in an expression form) always includes an else clause:
conditional_expression ::= or_test ["if" or_test "else" expression]
^^
In your reduce example you do supply it and, as a result, no errors are being raised.
In your first example, you don't specify what should be returned if the condition isn't true. Since python can't yield nothing from an expression, that is a syntax error. e.g:
a if b # SyntaxError.
a if b else c # Ok.
You might argue that it could be useful to implicitly yield None in this case, but I doubt that a proposal of that sort would get any traction within the community... (I wouldn't vote for it ;-)
While the others' explanations of why your code is causing a SyntaxError are completely accurate, the goal of my answer is to aid you in your goal "to at least learn how to use map() correctly."
Your use of map in this context does not make much sense. As you noted in your answer it would be much cleaner if you used a list comprehension:
[eng_swe[x] for x in l if x in eng_swe]
As you can see, this looks awfully similar to your map expression, minus some of the convolution. Generally, this is a sign that you're using map incorrectly. map(lambda... is pretty much a code smell. (Note that I am saying this as an ardent supporter of the use of map in Python. I know many people think it should never be used, but I am not one of those people, as long as it is used properly.)
So, you might be wondering, what is an example of a good time to use map? Well, one use case I can think of off the top of my head is converting a list of strs to ints. For example, if I am reading a table of data stored in a file, I might do:
with open('my_file.txt', 'r') as f:
data = [map(int, line.split(' ')) for line in f]
Which would leave me with a 2d-array of ints, perfect for further manipulation or analysis. What makes this a better use of map than your code is that it uses a built-in function. I am not writing a lambda expressly to be used by map (as this is a sign that you should use a list comprehension).
Getting back to your code, however... if you want to write your code functionally, you should really be using filter, which is just as important to know as map.
map(lambda x: eng_swe[x], filter(lambda x: eng_swe.get(x), l))
Note that I was unable to get rid of the map(lambda... code smell in my version, but at least I broke it down into smaller parts. The filter finds the words that can be translated and the map performs the actual translation. (Still, in this case, a list comprehension is probably better.) I hope that this explanation helps you more than it confuses you in your quest to write Python code functionally.

"is" not working in python IDE but working in command line

I couldn't understand why this is happening actually..
Take a look at this python code :
word = raw_input("Enter Word")
length = len(word)
if word[length-1:] is "e" :
print word + "d"
If I give input "love", its output must be "loved". So, when I wrote this in PyScripter IDE, its neither showing error nor the output. But I tried the same code in python shell, its working!
I'd like to know why this is happening.
The is keyword will only work if the strings have exactly the same identity, which is not guaranteed even if the strings have the same value. You should use == instead of is here to compare the values of the strings.
Or better still, use endswith:
if word.endswith("e"):
print word + "d"
You should use == in this case instead of is. Is checks for identity of objects, that is, id('e') would have to be equal with id of the string returned by the slice. As it happens, cpython stores one-letter strings (and small integers) as constants so this often works. But it is not reliable as any other implementation could not use this and then even "e" is "e" wouldn't have to yield True. Just use == and it should work.
edit: endswith mentioned by #MarkByers is even better for this case. safer, more readable and all that

Categories

Resources