Why my reverse() method doesn't work in python 3? - python

I was trying to do this exercise where you have to take a word and check if it's a palindrome. I tried to do it with making a string in to a list then reversing it and turning it back to a string, but the reverse method doesn't work for me for some reason, I checked and the usage is correct.
word = input('Give me a word:\n')
b = []
wordLetters = word.split()
b = wordLetters.reverse()
word2 = ''.join(b)
if word == word2:
print('Yay')
else:
print('heck')
it just shows
TypeError: can only join an iterable

In Python reverse method of list does the operation in-place e.g. it modifies the list you apply this operation to. This method has no return value.
l = [1, 2, 3, 4]
l.reverse()
print(l)
Output:
[4, 3, 2, 1]
If you try to get value returned by reverse you will get None:
print([1, 2, 3, 4].reverse())
Output:
None
If you need a reversed copy of your list you should use reversed function:
l = [1, 2, 3, 4]
r = reversed(l)
print(r)
print(list(r))
Output:
<list_reverseiterator object at 0x7ff37e288ef0>
[4, 3, 2, 1]
Notice that it returns iterator, not the list itself. You can pass that iterator to join function or you can build a list from it using list constructor.
The same is true for method sort and function sorted.

reverse() method of list doesn't return anything but reverses the list itself in Python 3. So join wordLetters not b.Hope this solves the issue.

As the documentation states:
list.reverse()
Reverse the elements of the list in place.
That means this method won't return anything (otherwise it would state what it returns) and that it reverses the list in-place.
Also str.split will (by default) split at whitespaces which is probably not intended from the problem description.
My suggestion would be to simply use slice notation for reversing the string:
word = input('Enter your word')
if word == word[::-1]:
print('Yay')
else:
print('heck')

Related

I want to clean the element in a list. If my list contains number 1 ans a stirng "1" i want to keep only one element either integer or sting

l = [1,2,3,4,5,'1','2','3','4','nag','nag','venkat',5,6,7]
l1 = []
for i in l:
if (str(i) not in l1) and (i not in l1):
l1.append(i)
print l1
I want to clean my list. My list contains numbers and strings. In the above list l i have both 1 and "1". I want to remove either 1 or "1". I want the output as [1, 2, 3, 4, 5, "nag", "venkat", 6, 7]
Confirmed in IDLE that this provides the output you're looking for. Also, I updated the names of some of your variables to be a little easier to understand.
my_list = [1,2,3,4,5,'1','2','3','4','nag','nag','venkat',5,6,7]
output_list = []
for i in my_list:
try:
if (str(i) not in output_list) and (int(i) not in output_list):
output_list.append(i)
except ValueError:
if i not in output_list:
output_list.append(i)
print output_list
In Python it's common practice to use variables assuming that they're a certain type and just catch errors, instead of going through the process of checking the type (int, str, etc) on each one. Here, inside the try statement, I'm assuming the loop variable i is either an int or a str that contains only numbers. Provided that's the case, this section works fine.
However, we know that the list contains some strings of letters, so the try block will throw a ValueError. The except block catches that and, knowing that this error will result from an attempt to cast a string of letters as an int (when we use int(i)), we can now safely assume that the loop variable i refers to a string of letters, which we then check against the output_list and append if needed. I hope that helps.
There's a way with list comprehensions, you create a new list, but this example only works if you know what you want to remove:
l1 = [i for i in l if i != "1" if i != "2" if i != "3" if i != "4"]
#output
[1, 2, 3, 4, 5, 'nag', 'nag', 'venkat', 5, 6, 7]
or for example only removing the string "1" it would be
l1 = [i for i in l if i != "1"]
Maybe it could be implemented in a function and a loop to remove such elements with a single if statement with this way. Not sure, anyway I'd go with coralv's way.

How to print items within lists in a list

Hear me out, I do not simply want someone to solve this problem for me. I know it is not 100% complete yet, but currently when I run the program I get an error about "Can't convert 'list' object to str implicitly" I'm looking for help on how to fix this and why it is does this.
Here is the problem
Write code to print out each thing in the list of lists, L, with a '*' after it like
1*2*3*4*...8*a*b*c*d*
This requires knowing the print statement and using the end or sep argument option
Here is my list, sorry for not putting it in earlier
L = [[1,2,3,4],[5,6,7,8],['a','b','c','d']]
Here is my code at the moment
def ball(x): #random function name with one parameter
q = '' #
i = 0
if type(x) != list: #verifies input is a list
return"Error"
for i in x: #Looks at each variable in list
for j in i: #Goes into second layer of lists
q = q + j + '*'
print(q)
The reason for your error
"Can't convert 'list' object to str implicitly"
is that you're using the wrong variable in your nested for loops. Where you're concatenating values to your q variable, you mistakenly put q = q + i when you wanted q = q + j. You also will want to cast the value of j as a string so it can be concatenated with q. In order to get your desired output, you can simply add an asterisk into that statement - something like the following: q = q + str(j) + '*'. On a completely unrelated note, your else statement that just has "Mistake" in it should be removed completely - it doesn't follow an if and it doesn't actually return or assign to a variable.
Note that this is not the most elegant way to go about solving this problem. I agree with ilent2 that you should take a look at both list comprehension and the str.join() method.
If you have a list of strings,
myList = ['a', '123', 'another', 'and another']
You can join them using the str.join function:
Help on method_descriptor:
join(...)
S.join(iterable) -> string
Return a string which is the concatenation of the strings in the
iterable. The separator between elements is S.
myString = '#'.join(myList)
If your list contains mixed types or non-strings you need to convert each item to a string first:
anotherList = [1, 2, 'asdf', 'bwsg']
anotherString = '*'.join([str(s) for s in anotherList])
You might want to read about list comprehension or more about the join function. Note, the above doesn't print the output (unless you are using the interactive console), if you want the output to be printed you will need call print too
print myString
print anotherString
And, if you are working with lists-of-lists you may need to change how you convert each sub-list into a string (depending on your desired output):
myListList = [[1, 2, 3, 4], [2, 3, 6, 5], [6, 4, 3, 1]]
myOtherString = '#'.join(['*'.join([str(s) for s in a]) for a in myListList])
The last line is a little complicated to read, you might want to rewrite it as a nested for loop instead.

Python List Comprehension Setting Local Variable

I am having trouble with list comprehension in Python
Basically I have code that looks like this
output = []
for i, num in enumerate(test):
loss_ = do something
test_ = do something else
output.append(sum(loss_*test_)/float(sum(loss_)))
How can I write this using list comprehension such as:
[sum(loss_*test_)/float(sum(loss_))) for i, num in enumerate(test)]
however I don't know how to assign the values of loss_ and test_
You can use a nested list comprehension to define those values:
output = [sum(loss_*test_)/float(sum(loss_))
for loss_, test_ in ((do something, do something else)
for i, num in enumerate(test))]
Of course, whether that's any more readable is another question.
As Yaroslav mentioned in the comments, list comprehensions don't allow you to save a value into a variable directly.
However it allows you to use functions.
I've made a very basic example (because the sample you provided is incomplete to test), but it should show how you can still execute code in a list comprehension.
def loss():
print "loss"
return 1
def test():
print "test"
return 5
output = [loss()*test() for i in range(10) ]
print output
which is this case will result in a list [5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
I hope this somehow shows how you could end up with the behaviour that you were looking for.
ip_list = string.split(" ") # split the string to a list using space seperator
for i in range(len(ip_list)): # len(ip_list) returns the number of items in the list - 4
# range(4) resolved to 0, 1, 2, 3
if (i % 2 == 0): ip_list[i] += "-" # if i is even number - concatenate hyphen to the current IP string
else: ip_list[i] += "," # otherwize concatenate comma
print("".join(ip_list)[:-1]) # "".join(ip_list) - join the list back to a string
# [:-1] trim the last character of the result (the extra comma)

"list index out of range" - Python

I was trying to write a piece of program that will remove any repeating items in the list, but I get a list index out of range
Here's the code:
a_list = [1, 4, 3, 2, 3]
def repeating(any_list):
list_item, comparable = any_list, any_list
for x in any_list:
list_item[x]
comparable[x]
if list_item == comparable:
any_list.remove(x)
print(any_list)
repeating(a_list)
So my question is, what's wrong?
Your code does not do what you think it does.
First you are creating additional references to the same list here:
list_item, comparable = any_list, any_list
list_item and comparable are just additional names to access the same list object.
You then loop over the values contained in any_list:
for x in any_list:
This assigns first 1, then 4, then 3, then 2, then 3 again to x.
Next, use those values as indexes into the other two references to the list, but ignore the result of those expressions:
list_item[x]
comparable[x]
This doesn't do anything, other than test if those indexes exist.
The following line then is always true:
if list_item == comparable:
because the two variables reference the same list object.
Because that is always true, the following line is always executed:
any_list.remove(x)
This removes the first x from the list, making the list shorter, while still iterating. This causes the for loop to skip items as it'll move the pointer to the next element. See Loop "Forgets" to Remove Some Items for why that is.
All in all, you end up with 4, then 3 items in the list, so list_item[3] then fails and throws the exception.
The proper way to remove duplicates is to use a set object:
def repeating(any_list):
return list(set(any_list))
because a set can only hold unique items. It'll alter the order however. If the order is important, you can use a collections.OrderedDict() object:
def repeating(any_list):
return list(OrderedDict.fromkeys(any_list))
Like a set, a dictionary can only hold unique keys, but an OrderedDict actually also keeps track of the order of insertion; the dict.fromkeys() method gives each element in any_list a value of None unless the element was already there. Turning that back in to a list gives you the unique elements in a first-come, first serve order:
>>> from collections import OrderedDict
>>> a_list = [1, 4, 3, 2, 3]
>>> list(set(a_list))
[1, 2, 3, 4]
>>> list(OrderedDict.fromkeys(a_list))
[1, 4, 3, 2]
See How do you remove duplicates from a list in whilst preserving order? for more options still.
The easiest way to solve your issue is to convert the list to a set and then, back to a list...
def repeating(any_list):
print list(set(any_list))
You're probably having an issue, because you're modifying the list (removing), while iterating over it.
If you want to remove duplicates in a list but don't care about the elements formatting then you can
def removeDuplicate(numlist):
return list(set(numlist))
If you want to preserve the order then
def removeDuplicate(numlist):
return sorted(list(set(numlist)), key=numlist.index)

making a string into a list within a list comprehension

What is asked:
By filtering the lowers list, create a list of the words which are at least 5 letters long and which have their letters already in alphabetical order.
What I have:
[word for word in lowers if len(word)>= 5 and word.sort=word]
I know that this will not work because the word.sort is being used on a string and word needs to be a list to make this function work. How would I do this in side the list comprehension or do i need to define something before.
>>> sorted('foo') == list('foo')
True
>>> sorted('bar') == list('bar')
False
The easiest way is to use list comprehension:
[word for word in lowers if len(word)>=5 and sorted(word)==list(word)]
Another is to use Python 2's filter function for stuff like this. Also, this uses string.join to convert sorted list back to string
#Lambda function to test condition
test = lambda x: len(x)>=5 and ''.join(sorted(x))==x
#Returns list of elements for which test is True
filter(test, lowers)
Plain ol' function (bonus: generators and yield!):
def filterwords(lst):
for word in lst:
if len(word)>=5 and sorted(word)==list(word):
yield word
The last one is most efficient, resource-wise and such.
Update: .sort() can be used on lists (not strings) to sort a list directly, but it does not return a value. So, list(word).sort() is of no use here; we use sorted(word).
>>> lst = [1,100,10]
>>> sorted(lst) #returns sorted list
[1, 10, 100]
>>> lst #is still the same
[1, 100, 10]
>>> lst.sort() #returns nothing
>>> lst #has updated
[1, 10, 100]

Categories