The below code provides the results I want (move the number to the front and 0 to the end of the list) on programminghero's playground. When I put it in a jupyter notebook the result is all 0's.
So, move_zero([0,1,0,2,0,3,0,5]) should return [1,2,3,5,0,0,0,0] but in jupyter it returns [0,0,0,0,0,0,0,0].
def move_zero(lst):
new_list = lst
counter = 0
for each in new_list:
if each == 0:
new_list.pop(counter)
new_list.append(0)
counter -= 1
counter += 1
return new_list
print(move_zero([0,1,0,2,0,3,0,5]))
It is recommended that you avoid modifying a list while iterating over the list. It is usually better to construct a new list:
def move_zero(lst):
non_zeros, zeros = [], []
for x in lst:
if x == 0:
zeros.append(x)
else:
non_zeros.append(x)
return non_zeros + zeros
print(move_zero([0,1,0,2,0,3,0,5])) # [1, 2, 3, 5, 0, 0, 0, 0]
Or maybe slightly less efficient but more concise:
def move_zero(lst):
return [x for x in lst if x] + [x for x in lst if not x]
redacted -- code had bug, not sure why it was accepted lol
Related
I want to find a sequence of n consecutive integers within a sorted list and return that sequence. This is the best I can figure out (for n = 4), and it doesn't allow the user to specify an n.
my_list = [2,3,4,5,7,9]
for i in range(len(my_list)):
if my_list[i+1] == my_list[i]+1 and my_list[i+2] == my_list[i]+2 and my_list[i+3] == my_list[i]+3:
my_sequence = list(range(my_list[i],my_list[i]+4))
my_sequence = [2,3,4,5]
I just realized this code doesn't work and returns an "index out of range" error, so I'll have to mess with the range of the for loop.
Here's a straight-forward solution. It's not as efficient as it might be, but it will be fine unless you have very long lists:
myarray = [2,5,1,7,3,8,1,2,3,4,5,7,4,9,1,2,3,5]
for idx, a in enumerate(myarray):
if myarray[idx:idx+4] == [a,a+1,a+2,a+3]:
print([a, a+1,a+2,a+3])
break
Create a nested master result list, then go through my_sorted_list and add each item to either the last list in the master (if discontinuous) or to a new list in the master (if continuous):
>>> my_sorted_list = [0,2,5,7,8,9]
>>> my_sequences = []
>>> for idx,item in enumerate(my_sorted_list):
... if not idx or item-1 != my_sequences[-1][-1]:
... my_sequences.append([item])
... else:
... my_sequences[-1].append(item)
...
>>> max(my_sequences, key=len)
[7, 8, 9]
A short and concise way is to fill an array with numbers every time you find the next integer is the current integer plus 1 (until you already have N consecutive numbers in array), and for anything else, we can empty the array:
arr = [4,3,1,2,3,4,5,7,5,3,2,4]
N = 4
newarr = []
for i in range(len(arr)-1):
if(arr[i]+1 == arr[i+1]):
newarr += [arr[i]]
if(len(newarr) == N):
break
else:
newarr = []
When the code is run, newarr will be:
[1, 2, 3, 4]
#size = length of sequence
#span = the span of neighbour integers
#the time complexity is O(n)
def extractSeq(lst,size,span=1):
lst_size = len(lst)
if lst_size < size:
return []
for i in range(lst_size - size + 1):
for j in range(size - 1):
if lst[i + j] + span == lst[i + j + 1]:
continue
else:
i += j
break
else:
return lst[i:i+size]
return []
mylist = [2,3,4,5,7,9]
for j in range(len(mylist)):
m=mylist[j]
idx=j
c=j
for i in range(j,len(mylist)):
if mylist[i]<m:
m=mylist[i]
idx=c
c+=1
tmp=mylist[j]
mylist[j]=m
mylist[idx]=tmp
print(mylist)
I want to have a function that will return the reverse of a list that it is given -- using recursion. How can I do that?
Append the first element of the list to a reversed sublist:
mylist = [1, 2, 3, 4, 5]
backwards = lambda l: (backwards (l[1:]) + l[:1] if l else [])
print backwards (mylist)
A bit more explicit:
def rev(l):
if len(l) == 0: return []
return [l[-1]] + rev(l[:-1])
This turns into:
def rev(l):
if not l: return []
return [l[-1]] + rev(l[:-1])
Which turns into:
def rev(l):
return [l[-1]] + rev(l[:-1]) if l else []
Which is the same as another answer.
Tail recursive / CPS style (which python doesn't optimize for anyway):
def rev(l, k):
if len(l) == 0: return k([])
def b(res):
return k([l[-1]] + res)
return rev(l[:-1],b)
>>> rev([1, 2, 3, 4, 5], lambda x: x)
[5, 4, 3, 2, 1]
I know it's not a helpful answer (though this question has been already answered), but in any real code, please don't do that. Python cannot optimize tail-calls, has slow function calls and has a fixed recursion depth, so there are at least 3 reasons why to do it iteratively instead.
The trick is to join after recursing:
def backwards(l):
if not l:
return
x, y = l[0], l[1:]
return backwards(y) + [x]
Use the Divide & conquer strategy. D&C algorithms are recursive algorithms.
To solve this problem using D&C, there are two steps:
Figure out the base case. This should be the simplest possible case.
Divide or decrease your problem until it becomes the base case.
Step 1: Figure out the base case. What’s the simplest list you could
get? If you get an list with 0 or 1 element, that’s pretty easy to sum up.
if len(l) == 0: #base case
return []
Step 2: You need to move closer to an empty list with every recursive
call
recursive(l) #recursion case
for example
l = [1,2,4,6]
def recursive(l):
if len(l) == 0:
return [] # base case
else:
return [l.pop()] + recursive(l) # recusrive case
print recursive(l)
>[6,4,2,1]
Source : Grokking Algorithms
This one reverses in place. (Of course an iterative version would be better, but it has to be recursive, hasn't it?)
def reverse(l, first=0, last=-1):
if first >= len(l)/2: return
l[first], l[last] = l[last], l[first]
reverse(l, first+1, last-1)
mylist = [1,2,3,4,5]
print mylist
reverse(mylist)
print mylist
def revList(alist):
if len(alist) == 1:
return alist #base case
else:
return revList(alist[1:]) + [alist[0]]
print revList([1,2,3,4])
#prints [4,3,2,1]
A recursive function to reverse a list.
def reverseList(lst):
#your code here
if not lst:
return []
return [lst[-1]] + reverseList(lst[:-1])
print(reverseList([1, 2, 3, 4, 5]))
def reverse(q):
if len(q) != 0:
temp = q.pop(0)
reverse(q)
q.append(temp)
return q
looks simpler:
def reverse (n):
if not n: return []
return [n.pop()]+reverse(n)
Take the first element, reverse the rest of the list recursively, and append the first element at the end of the list.
def reverseList(listName,newList = None):
if newList == None:
newList = []
if len(listName)>0:
newList.append((listName.pop()))
return reverseList(listName, newList)
else:
return newList
print reverseList([1,2,3,4])
[4,3,2,1]
Using Mutable default argument and recursion :
def hello(x,d=[]):
d.append(x[-1])
if len(x)<=1:
s="".join(d)
print(s)
else:
return hello(x[:-1])
hello("word")
additional info
x[-1] # last item in the array
x[-2:] # last two items in the array
x[:-2] # everything except the last two items
Recursion part is hello(x[:-1]) where its calling hello function again after x[:-1]
This will reverse a nested lists also!
A = [1, 2, [31, 32], 4, [51, [521, [12, 25, [4, 78, 45], 456, [444, 111]],522], 53], 6]
def reverseList(L):
# Empty list
if len(L) == 0:
return
# List with one element
if len(L) == 1:
# Check if that's a list
if isinstance(L[0], list):
return [reverseList(L[0])]
else:
return L
# List has more elements
else:
# Get the reversed version of first list as well as the first element
return reverseList(L[1:]) + reverseList(L[:1])
print A
print reverseList(A)
Padmal's BLOG
You can reduce the recursion depth by half by swapping the first and last elements at once and calling rev recursively on the middle of the list:
lks=[2,7,3,1,9,6,5]
def rev(lks):
if len(lks)<2:
return lks
return [lks[-1]]+rev(lks[1:-1])+[lks[0]]
print(rev(lks))
The answer you're looking for is inside the function. The rest of the stuff is just to see (or if you want to compare) the time taken by the different algorithms.
import time
import sys
sys.setrecursionlimit(10**6)
def reverse(ls1):
if len(ls1) <= 1:
return ls1
else:
ls1[0], ls1[-1] = ls1[-1], ls1[0]
return [ls1[0]] + reverse(ls1[1:-1]) + [ls1[-1]]
ls = [*range(2000)]
start_time = time.time()
print(reverse(ls))
stop_time = time.time()
print(f"Total time taken: {(stop_time - start_time) * 1000} msec.")
Why not:
a = [1,2,3,4,5]
a = [a[i] for i in xrange(len(a)-1, -1, -1)] # now a is reversed!
if it is a list of numbers easiest way to reverse it would be. This would also work for strings but not recommended.
l1=[1,2,3,4]
l1 = np.array(l1)
assert l1[::-1]==[4,3,2,1]
if you do not want to keep it as a numpy array then you can pass it into a list as
l1 = [*l1]
again I do not recommend it for list of strings but you could if you really wanted to.
def reverse_array(arr, index):
if index == len(arr):
return
if type(arr[index]) == type([]):
reverse_array(arr[index], 0)
current = arr[index]
reverse_array(arr, index + 1)
arr[len(arr) - 1 - index] = current
return arr
if __name__ == '__main__':
print(reverse_array([[4, 5, 6, [4, 4, [5, 6, 7], 8], 8, 7]], 0))
def disp_array_reverse(inp, idx=0):
if idx >= len(inp):
return
disp_array_reverse(inp, idx+1)
print(inp[idx])
So, I`m trying to write a function that removes the negative elements of a list without using .remove or .del. Just straight up for loops and while loops. I don`t understand why my code doesn`t work. Any assistance would be much appreciated.
def rmNegatives(L):
subscript = 0
for num in L:
if num < 0:
L = L[:subscript] + L[subscript:]
subscript += 1
return L
Why not use list comprehension:
new_list = [i for i in old_list if i>=0]
Examples
>>> old_list = [1,4,-2,94,-12,-1,234]
>>> new_list = [i for i in old_list if i>=0]
>>> print new_list
[1,4,94,234]
As for your version, you are changing the elements of the list while iterating through it. You should absolutely avoid it until you are absolutely sure what you are doing.
As you state that this is some sort of exercise with a while loop, the following will also work:
def rmNegatives(L):
i = 0
while i < len(L):
if L[i]<0:
del L[i]
else:
i+=1
return L
You could also use filter, if you so please.
L = filter(lambda x: x > 0, L)
A note to your code:
L = L[:subscript] + L[subscript:]
does not change your list. For example
>>> l = [1,2,3,4]
>>> l[:2] + l[2:]
[1, 2, 3, 4]
Other mistakes:
def rmNegatives(L):
subscript = 0
for num in L: # here you run over a list which you mutate
if num < 0:
L = L[:subscript] + L[subscript:] # here you do not change the list (see comment above)
subscript += 1 # you have to do this only in the case, when you did not remove an element from the list
return L
A running code would be:
def rmNegatives(L):
subscript = 0
for num in list(L):
if num < 0:
L = L[:subscript] + L[subscript+1:]
else:
subscript += 1
return L
See the solutions of #Aesthete and #sshashank124 for better implementations of your problem...
This question already has answers here:
Python Homework - creating a new list
(6 answers)
Closed 9 years ago.
I am trying to write a function called splitList(myList, option) that takes a list and an option which is either 0 or 1 as parameters. If the value of the option is 0 the function returns a list consisting of the elements in myList that are negative and if the value of the option is 1 the function returns a list consisting of the elements in myList that are even (we consider 0 to be an even number, since it is evenly divisible by 2).
For example:
splitList([1,-3,5,7,-9,-11,0,2,-4], 0)
Would return the list:
[-3,-9,-11,-4]
Where as:
splitList([1,-3,5,7,-9,-11,0,2,-4], 1)
Would return the list:
[0,2,-4]
For this problem I must use a for loop.
Here is what I have:
def splitList(myList, option):
negativeValues = []
positiveValues = []
evenValues = []
for i in range(0,len(myList)):
if myList[i] < 0:
negativeValues.append(myList [i])
else:
positiveValues.append(myList [i])
for element in myList:
if option == 1:
myList [i] % 2 == 0
evenValues.append(myList [i])
return evenValues
else:
return negativeValues
The only thing I cannot get it to do is to is sort the list and return all the numbers that are divisible by 2.
Using a loop is a bit redundant here since there's a standard function filter that does what you want: returns a new list with these elements of a list which match a given predicate.
Let's define the predicates first:
def is_even(x):
return x % 2 == 0
def is_negative(x):
return x < 0
Then you can easily define your function in terms of filter:
def splitList(myList, option):
predicate = is_negative if option == 0 else is_even
return filter(predicate, myList)
You can build all your variants from these primitives:
def even_list(numbers):
return [x for x in numbers if not (x & 1)]
def odd_list(numbers):
return [x for x in numbers if x & 1]
def negative_list(numbers):
return [x for x in numbers if x < 0]
def positive_list(numbers):
return [x for x in numbers if x > 0]
Then test:
>>> def test():
... numbers = list(range(-3, 4))
... print even_list(numbers)
... print odd_list(numbers)
... print positive_list(numbers)
... print negative_list(numbers)
...
>>> test()
[-2, 0, 2]
[-3, -1, 1, 3]
[1, 2, 3]
[-3, -2, -1]
Later: so stealing from #Kos, you could write split_list like this:
def split_list(myList, option):
predicate = negative_list if not option else even_list
return predicate(myList)
Or:
def split_list(myList, option):
predicates = [negative_list, even_list]
return predicates[option](myList)
Not sure if it meets your needs if the for-loop is in a list comprehension in a called function.
Also: "Function names should be lowercase, with words separated by underscores as necessary to improve readability."
You return too soon. You first have to complete the foor loop and return after it, not from inside the loop.
Example
for i in range(5):
print i
numbers.append(i)
return numbers //wrong: exit the function on the first pass in the loop.
for i in range(5):
print i
numbers.append(i)
return numbers //right
Besides that why do you calculate the negative valuse list if you don't need it?
def splitList(myList,option):
negative_numbers = [i for i in myList if i < 0]
even_numbers = [i for i in myList if i % 2 == 0]
return sorted(even_numbers) if option else sorted(negative_numbers)
I believe this is what you where trying to achieve:
def splitList(myList,option):
result = []
if option == 0:
for item in myList:
if (item < 0):
result.append(item)
elif option == 1:
for item in myList:
if (item % 2 == 0):
result.append(item)
else:
return "Option Error"
return sorted(result)
print splitList([1,-3,5,7,-9,-11,0,2,-4], 0)
print splitList([1,-3,5,7,-9,-11,0,2,-4], 1)
print splitList([1,-3,5,7,-9,-11,0,2,-4], 2)
Outputs:
[-11, -9, -4, -3]
[-4, 0, 2]
Option Error
I'm trying to answer this question on a practice test:
Write a function, def eliminate(x, y), that copies all the elements of the list x except the largest value into the list y.
The best thing I could come up with is:
def eliminate(x, y):
print(x)
y = x
big = max(y)
y.remove(big)
print(y)
def main():
x = [1, 3, 5, 6, 7, 9]
y = [0]
eliminate(x, y)
main()
I don't think that'll cut it if a question like that comes up on my final, and I'm pretty sure I shouldn't be writing a main function with it, just the eliminate one. So how would I answer this? (keep in mind this is an introductory course, I shouldn't be using more advanced coding)
I'd probably do this:
def eliminate(x, y):
largest = max(x)
y[:] = [elem for elem in x if elem != largest]
This fills y with all the elements in x except whichever is largest. For example:
>>> x = [1,2,3]
>>> y = []
>>> eliminate(x, y)
>>> y
[1, 2]
>>> x = [7,10,10,3,4]
>>> eliminate(x, y)
>>> y
[7, 3, 4]
This assumes that by "copies" the question is asking for the contents of y to be replaced. If the non-maximal elements of x are to be appended to y, you could use y.extend instead.
Note that your version doesn't handle the case where there are multiple elements with the maximum value (e.g. [1,2,2]) -- .remove() only removes one of the arguments, not all of them.
In order to find the largest number in a list you will need to iterate over that list and keep trace of the largest element along the way. There are several ways to achieve this.
So this code answers the question:
y.extend([n for n in x if n != max(x)])
but i'm worried it might not solve your problem, which is learning how and why this works. Here is that code expanded into a very straight forward way that just uses for loops and if statments.
def trasfer_all_but_largest(transfer_from_list, transfer_to_list):
current_index = 0
index_of_current_largest_element = 0
largest_element_so_far = None
for element in transfer_from_list:
if current_index == 0:
largest_element_so_far = element
else:
if element > largest_element_so_far:
largest_element_so_far = element
index_of_current_largest_element = current_index
current_index = current_index + 1
index_of_largest_element = index_of_current_largest_element
current_index = 0 # reset our index counter
for element in transfer_from_list:
if current_index == index_of_largest_element:
continue # continue means keep going through the list
else:
transfer_to_list = transfer_to_list + [element]
current_index = current_index + 1
return transfer_to_list
list_with_large_number = [1, 2, 100000]
list_were_transfering_to = [40, 50]
answer_list = trasfer_all_but_largest(list_with_large_number, list_were_transfering_to)
print(answer_list)