How to Reverse Lists in Python, Getting "Nonetype" as List

Unable to reverse lists in Python, getting Nonetype as list

As jcomeau mentions, the .reverse() function changes the list in place. It does not return the list, but rather leaves qSort altered.

If you want to 'return' the reversed list, so it can be used like you attempt in your example, you can do a slice with a direction of -1

So replace print qSort.reverse() with print qSort[::-1]


You should know slices, its useful stuff. I didn't really see a place in the tutorial where it was all described at once, (http://docs.python.org/tutorial/introduction.html#lists doesn't really cover everything) so hopefully here are some illustrative examples.

Syntax is: a[firstIndexInclusive:endIndexExclusive:Step]

>>> a = range(20)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> a[7:] #seventh term and forward
[7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> a[:11] #everything before the 11th term
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> a[::2] # even indexed terms. 0th, 2nd, etc
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>> a[4:17]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
>>> a[4:17:2]
[4, 6, 8, 10, 12, 14, 16]
>>> a[::-1]
[19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> a[19:4:-5]
[19, 14, 9]
>>> a[1:4] = [100, 200, 300] #you can assign to slices too
>>> a
[0, 100, 200, 300, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

How can I get a reversed copy of a list (avoid a separate statement when chaining a method after .reverse)?

You can use reversed(formation) to return a reverse iterator of formation. When you call formation.reverse() it does an in place reversal of the list and returns None.

EDIT:

I see what you are trying to do now, in my opinion it's easier to just do this with a list comprehension:

def solution(formation):
return len([k for k in formation[formation.index(bCamel)+1:] if k == fCamel]) == 0

This basically looks at all the elements after the first bCamel and collects all the elements that have the value fCamel. If that list has a length == 0 you have a solution.

Here's a few examples:

>>> k = ['F','F','B','B','F']
>>> solution(k)
False
>>> k = ['F','F','B','B','B']
>>> solution(k)
True
>>> k = ['F','F','B','F','F','B','B']
>>> solution(k)
False
>>>

Why am I getting a NoneType error after reversing a linked list and processing the head of the new linked list?

The reason for the error is that you cannot assume that both prev and prev2 are not None. Your while condition only guarantees that at least one of them is not None, but not both. So that means you still need to have a None check inside the body of the loop.

There are also some other issues:

  • l1==[0]: is not correct. The left side of this comparison is a linked list instance, while the right side is a standard list. These comparisons will always be False, and so you can just omit them

  • You are adding the carry to the wrong sum. You should add the carry from the previous iteration to the current sum, so things are currently happing in the wrong order.

  • The resulting list should be reversed. You can do this on the fly by prefixing each node to l3, instead of appending it. This will also make it unnecessary to create a dummy ListNode(0) before the final loop. You can just start with None.

  • Your code mutates the original input lists. This will be acceptable on code challenge sites, and be efficient, but it is bad practice. The caller should not be unpleasantly surprised that the lists they provide as input have been reversed by a call to this addTwoNumbers function. You can solve this in several ways, but it is probably easiest to reverse them a second time to undo that operation.

  • To avoid repetition of code, you should create a reverse function

I'll assume that the ListNode constructor can take a second argument for initialising its next reference:

class ListNode:
def __init__(self, val, nxt=None):
self.val = val
self.next = nxt

Then the corrected code could be:

class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:

def reverse(lst: ListNode):
prev = None
node = lst
while node:
curr = node.next
node.next = prev
prev = node
node = curr
return prev

#Reversing both linked lists l1 & l2
l1 = reverse(l1)
l2 = reverse(l2)

#Creating a new linked list that is the addition of the two reversed linked list
node1 = l1
node2 = l2
l3 = None
carry = 0

while node1 or node2:
added = carry # The carry from the previous iteration should be used
if node1: # You must have this check
added += node1.val
node1 = node1.next
if node2:
added += node2.val
node2 = node2.next
carry = added // 10 # Simpler way to get the carry
l3 = ListNode(added % 10, l3) # Prefix(!) the new node

if carry == 1:
l3 = ListNode(1, l3)

# Restore the input lists:
reverse(l1)
reverse(l2)
return l3

Further remarks

Concerning the prefixing of nodes into the final list l3:

This is the main statement for doing that:

l3 = ListNode(added % 10, l3)

Let's break this down:

The constructor is called with two arguments:

  • val = added % 10: this is one digit, so in case added is 14, this expression will evaluate to just 4 (the 1 will go to the carry).
  • nxt = l3: this is the current (incomplete) list. The first time it is None.

The constructor then assigns these values as attributes of the new node that is being initialised:

self.val = val
self.next = nxt

So here we see that the value of nxt, is assigned to the new node's next attribute. As we passed l3 as argument, we are actually doing:

self.next = l3

By that statement we effectively prefix the new node to the list: the new node becomes the first node of the list. Moreover, self acts as the head of that list, which is now one node longer. We want to keep track of this new head, and so we assign the new node back to l3:

l3 = ListNode(added % 10, l3)

As the first time l3 was None, this will just create a one-node list, whose next attribute is that None. But the second time this is executed, we get a new node whose next refers to the "existing" node, so now we have a list of two... etc.

Sometimes it can come in handy to start a linked list with a dummy node like ListNode(0), which then later can be removed. However, in this revised algorithm that would not help, and so we start with None, which after the first iteration of the loop will serve as second argument to the ListNode constructor, which in turn will use it to initialise the next attribute of the new node. This new node will remain the tail of the list as other nodes are prefixed to it.

TypeError: 'NoneType' object is not iterable over list

The problem is here:

spaces = stars.reverse()

reverse, like append, operates in-place and returns nil. To return a new list you need to do:

spaces = list(reversed(stars))

I must say though, I don't understand the point of your iterat generator. If you left spaces and stars as generators in the first place, you wouldn't need it at all:

stars = range(number)
spaces = reversed(stars)
for star,space in zip(stars, spaces):
print(" "*(space-1)+"*"*((star*2)-1))

The error comes as can only concatenate list (not NoneType) to list

.reverse() is an inplace operation. It won't return the reversed list, it returns None

Use sorted(list1, reverse=True).

def combine_lists(list1, list2):
# Generate a new list containing the elements of list2
# Followed by the elements of list1 in reverse order
return(list2+sorted(list1, reverse=True))

Jamies_list = ["Alice", "Cindy", "Bobby", "Jan", "Peter"]
Drews_list = ["Mike", "Carol", "Greg", "Marcia"]

print(combine_lists(Jamies_list, Drews_list))

ELSE

def combine_lists(list1, list2):
# Generate a new list containing the elements of list2
# Followed by the elements of list1 in reverse order
list1.reverse()
return(list2+list1)

Jamies_list = ["Alice", "Cindy", "Bobby", "Jan", "Peter"]
Drews_list = ["Mike", "Carol", "Greg", "Marcia"]

print(combine_lists(Jamies_list, Drews_list))

ELSE

def combine_lists(list1, list2):
# Generate a new list containing the elements of list2
# Followed by the elements of list1 in reverse order
return list2 + list1[::-1]

Jamies_list = ["Alice", "Cindy", "Bobby", "Jan", "Peter"]
Drews_list = ["Mike", "Carol", "Greg", "Marcia"]

print(combine_lists(Jamies_list, Drews_list))

Interger List Reversal producing a NoneType Error

You're setting reversed_numbers = reversed_numbers.insert(i, some_numbers.pop()) when you just need to call insert() on reversed_numbers (without reassigning values).

some_numbers = [1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77]
reversed_numbers = []
i = 0
while some_numbers:
reversed_numbers.insert(i, some_numbers.pop())
i += 1

print(reversed_numbers)

Also note that your post has i = 0 inside your while loop, so you'd be overwriting the same index every time.

Appending turns my list to NoneType

list.append is a method that modifies the existing list. It doesn't return a new list -- it returns None, like most methods that modify the list. Simply do aList.append('e') and your list will get the element appended.

list.reverse() is not working

reverse modifies the list in place and returns None. If you do

l.reverse()
print l

you will see your list has been modified.

For merging 2 sorted linked list in reverse order I am getting AttributeError 'NoneType' object has no attribute 'next' for some of the testcases. Why

The problem is in this line:

elif p2.data<p1.data:

There shouldn't be a condition here, as you want to deal with all remaining cases. Right now you don't treat the case where p2.data is equal to p1.data. So change the above line to:

else:

This will fix the issue.

Alternative

There is a shorter way to achieve the result: instead of reversing the list in a second phase, insert the nodes in reverse order directly. That way you can deal with the job in one loop instead of two. You should then continue the loop as long as one of the references is not None, so the while condition becomes an or. Then in the if condition you need to consider that one of the two could be None. Finally, you don't really need to introduce p1 and p2 variables: just use the already given h1 and h2.

This solution also doesn't need the temporary "sentinel" node (the one with value -1).

def mergeResult(h1,h2):
result = None
while h1 or h2:
if not h2 or (h1 is not None and h1.data < h2.data):
h1.next, result, h1 = result, h1, h1.next
else:
h2.next, result, h2 = result, h2, h2.next
return result

So here h1 (or h2) is prepended to the current result list. After it is prepended, the result reference is put to that prepended node. The multiple assignment is such that h1 (or h2) will still walk to the (original) next node, before that node's next reference is adjusted. You can of course also do this with separate assignments, but then you need a temporary variable:

def mergeResult(h1,h2):
result = None
while h1 or h2:
if not h2 or (h1 is not None and h1.data < h2.data):
nxt = h1.next
h1.next = result
result = h1
h1 = nxt
else:
nxt = h2.next
h2.next = result
result = h2
h2 = nxt
return result


Related Topics



Leave a reply



Submit