reverse() does not work on a Python literal? - python

Why doesn't this work in Python?
>>> print [0,1,0,1,1,0,1,1,1,0,1,1,1,1,0].reverse()
None
I expected to get back the list in reverse order.

>>> a = [3, 4, 5]
>>> print a.reverse()
None
>>> a
[5, 4, 3]
>>>
It's because reverse() does not return the list, rather it reverses the list in place. So the return value of a.reverse() is None which is shown in the print.

If you want it to return a new list in reverse order, you can use [::-1]
>>> [0,1,0,1,1,0,1,1,1,0,1,1,1,1,0][::-1]
[0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0]
As I'm still trying to understand the downvote, if it doesn't matter that the original list gets changed, use #taskinoor's answer, it'll be faster.
However if you're required to keep the original list unchanged, I suggest you to use [::-1].
from time import time
lst = [0,1,0,1,1,0,1,1,1,0,1,1,1,1,0]
s = time()
for i in xrange(5000000):
a = lst[::-1] # creates a reversed list
print time() -s
s = time()
for i in xrange(5000000):
b = lst[:] # copies the list
b.reverse() # reverses it
print time() -s
outputs
2.44950699806
3.02573299408

If you want reversed copy of a list, use reversed:
>>> list(reversed([1,2,3,4]))
[4, 3, 2, 1]
p.s. reversed returns an iterator instead of copy of a list (as [][::1] does). So it is suitable then you need to iterate through a reversed iterable. Additional list() here used only for the demonstration.

Just to complement other answers. Do not forget:
>> reversed_iterator = reversed([0,1,0,1,1,0,1,1,1,0,1,1,1,1,0])
>> print list(reversed_iterator)
[0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0]
This way your list is unchanged if this is a requierement.

reverse changes a list variable as seen here
list reverse
if you print it after you reversed it it will show up correctily
so just use a variable

Related

Is it possible to add the output of a generator when making a list in Python?

Is it possible to make a generator's output be added into a list creation, without making a nested list in Python?
I have tried the following code, but it only gives me a generator object, and not the items.
x = 5
expected_list = [3, 0, 0, 0, 0, 0, 3]
list = [3, 0 for i in range(x), 3]
print(list)
I get this error whenever trying to run this code:
list = [3, 0 for i in range(x), 3]
^^^^
SyntaxError: did you forget parentheses around the comprehension target?
If I put parentheses around 0 for i in range(x), I get the list
[3, <generator object <genexpr> at 0x000001A065179A10>, 3]
I would like for the generator object to return 0, 0, 0, 0, 0, without creating a list inside of my list.
Unpack it:
[3, *(0 for i in range(x)), 3]

How can be used a list comprehension at left side of an assignment operator?

My code part is:
v=[7,0,2,5,1] # list with any numbers
x={2,0,4} # set of indexes (where element of x < len(v) has been provided)
for i in x: # this for loop is working
v[i]-=10
print(v) # good result
[-3, 0, -8, 5, -9]
My question is how can I replace the for cycle above with list comprehension or other more compact expression?
Note: the print only shows the new values of v
but the task would be modifying only some element of original v list.
This doesn't quite answer the question but unless you're trying for some code golfing contest I hope you just go with the below. It is simple and clear - just because the code will fit in one line doesn't make it better.
for i in x:
v[i] -= 10
I think you need:
v = [i-10 if idx in x else i for idx,i in enumerate(v)])
print(v)
Output:
[-3, 0, -8, 5, -9]
May be there is not too much reason to do a list comprehension on the left side of assignment op.,
moreover of modify assignment op. but nevertheless I wanted to construct this.
So the question was how could I modify some element by an index set
in a longer list with list comprehension (without any copy of list or usage of explicit cycle statement) .
I could achieve this solution only with "self writing" code by using exec() function.
First of all I show a simple assignment with same value:
# Let the index set and the "long" list be:
>>> x={0, 2, 4}
>>> v=[0]*10
>>> str(tuple("v["+str(i)+"]" for i in x))+"="+str(len(x)*(1,))
"('v[0]', 'v[2]', 'v[4]')=(1, 1, 1)"
# So I needed to change ("'" to "") at the left side before I could execute it.
>>> str(tuple("v["+str(i)+"]" for i in x)).replace("'","")+"="+str(len(x)*(1,))
'(v[0], v[2], v[4])=(1, 1, 1)'
# Put it into `exec()` function.
>>> exec(str(tuple("v["+str(i)+"]" for i in x)).replace("'","")+"="+str(len(x)*(1,)))
>>> v
[1, 0, 1, 0, 1, 0, 0, 0, 0, 0]
Now I show how I can decrease the list element by 1 according x set (as it was my question):
>>> s1=str(tuple("v["+str(i)+"]-=1" for i in x))
>>> s1
"('v[0]-=1', 'v[2]-=1', 'v[4]-=1')"
# Now I used the REG module for more efficient character replacement.
>>> import re as r
>>> r.sub(r"\(|\)|'","",s1).replace(",",";")
v[0]-=1; v[2]-=1; v[4]-=1'
# Now put them together:
>>> exec(r.sub(r"\(|\)|'","",str(tuple("v["+str(i)+"]-=1" for i in x))).replace(",",";"))
>>> v
[-1, 0, -1, 0, -1, 0, 0, 0, 0, 0] # if v was 10*[0]
You can try list comprehension:
print([v - 10 if i in x else v for i,v in enumerate(v)])
I think below is what you need
[v[i]-10 if i in x else v[i] for i in range(len(v))]
[-3, 0, -8, 5, -9]

Unexpected list append

import random
stats = []
statslist = []
rollslist = []
for var1 in range(4):
stats.append(random.randrange(1, 7))
rollslist.append(stats)
print(stats)
b = min(stats)
stats.remove(b)
print(sum(stats))
statslist.append(sum(stats))
print(stats)
print(rollslist)
print(statslist)
actual result
[5, 1, 1, 3]
9
[5, 1, 3]
[[5, 1, 3]]
[9]
expected result
[5, 1, 1, 3]
9
[5, 1, 3]
[[5, 1, 1, 3]]
[9]
I'm expecting it to print four numbers for the fourth result instead of the three it's giving me. I appended the list before the number was removed. What am I missing?
You added a mutable list. When you modified it later, the modification affected the object you placed in the list, because it was a direct reference and not a copy.
The easiest way to make a copy of a list is to use slicing:
rollslist.append(stats[:])
as Avinash mentioned, it's because you're still referring to the stats list. Meaning, changes made later (like the removal of an item) will still be reflected. For the expected behaviour, you can make a copy of the list like so:
newCopy = list(stats)
rollslist.append(newCopy)

How to reverse a stack without returning anything

a={}#dictionary
b=0
while(stack.is_empty()==False):
b=b+1
a={b:stack.pop()}
else:
for i in range(b, 0, -1):
stack.push(a[i])
I think this should work but it doesn't,
Key error and empty stack errors are raised
For reversing a stack, you can consider the stack as a list and do:
stack.reverse()
instead of popping and pushing in a spare stack. From Python 2 documentation:
Reverse the elements of the list, in place
>>> a = [66.25, 333, 333, 1, 1234.5]
>>> a.reverse()
>>> a
[333, 1234.5, 1, 333, -1, 66.25]
EDIT: As rephrased by the questioner, if you want to reverse a stack into a new one, you can do:
def reverse_and_return(stack):
newstack = [] # New list/stack
for element in stack:
newstack.insert(0, element) # Push new element first
return newstack
a={b:stack.pop()}
That will replace a with a new dictionary each iteration. To add keys to the existing dictionary, do
a[b] = stack.pop()
If I correctly understood, try
>>> {'b':[1, 2, 3, 4, 5][::-1]}
{'b': [5, 4, 3, 2, 1]} #list inside a dictionary are reversed

list inside list python

I am not looking to get an list inside list instead I just want to add zeros but do not know how. see code
def myconv(x,h):
q=[]
print(h)
for i in range(len_h):
q.append(h[len_h-1-i])
print(q)
q.insert(0,([0]*len_h)) #I want this to add just plain zeros to the array... not an array insdie an
#like it is doing here
q.insert(len(q)+1,(0]*len_h))
print(q)
print(myconv([6,7,8,9],[1,2,3,4,5,6,7,8,9,0]))
You want to use +, e.g. [0, 0, 0] + [2, 1, 3] == [0, 0, 0, 2, 1, 3], to concatenate an array onto the first. Otherwise, you'll need to insert (or append) items one at a time.
To demonstrate how list multiplication works:
>>> [0]*2
[0, 0]
>>> [0]*5
[0, 0, 0, 0, 0]
I prefer the in-place extend operation. Just don't assign to it, because like most all Python in-place methods, it returns None.
>>> l2.extend([0]*5)
>>> l2
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0]
You have two ways of doing this:
q = [0]*len_h + q
or
q[0:0] = [0]*len_h
q.insert(0,([0]*len_h))
This creates a list within a list because [0]*len_h creates a new list. This array is then inserted into q. Instead, insert each element into q without creating a new list.
for i in range(len_h):
q.insert(0, 0)

Categories

Resources