Removing Negative Elements in a List - Python - python

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...

Related

Two different results

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

Random walk Python exercise loop

I am doing python exercise and I can not finish it. I need to a create array and fill it 25 numbers, every number will be the sum of previous one and the value drawn from the set (-5, 5).
import numpy as np
import random
def prog_list(mylist):
mylist = [0]
addlist = [-5,5]
sum_list = 0
for i in mylist:
if len(mylist) < 25:
sum_list = random.choice(addlist) + mylist[i-1]
mylist.append(sum_list)
else:
return mylist
for x in prog_list(mylist):
print(x)
When I print x I've got
IndexError: list index out of range
this works:
def prog_list(n):
mylist = [0]
#addlist = [-5,5]
addlist = list(range(-5, 5+1))
for i in range(1, n):
_sum = random.choice(addlist) + mylist[i-1]
mylist.append(_sum)
return mylist
prog_list(25)
if you want to draw any integer from (-5, 5) you need this:
addlist = list(range(-5, 5+1))
there is an even cleaner way to do it where you dont acces the list in every iteration:
def prog_list(n):
mylist = []
_sum = 0
#addlist = [-5,5]
addlist = list(range(-5, 5+1))
for i in range(n):
mylist.append(_sum)
_sum += random.choice(addlist)
return mylist
prog_list(25)
for i in mylist:
if len(mylist) < 100:
sum_list = random.choice(addlist) + mylist[i-1]
mylist.append(sum_list)
else:
return mylist
This construct will get value of element of mylist as i. First element is 0 so you get one of {-5,5} + mylist[-1] ([-1] means last element in python language), this result in either -5 or 5, then you get that value less 1 which is either -6 or 4, but there is not enough elements to get -6 (i.e. 6 from right) or 4 (i.e. 5 from left) element, thus IndexError. To avoid that you might replace your for using following while
while len(mylist) < 100:
sum_list = random.choice(addlist) + mylist[-1]
mylist.append(sum_list)
return mylist
for i in mylist
iterates over the items in your list, so on the first step when you add or subtract 5, you will be trying to access the (5 - 1)th or the (-5 - 1)th element with mylist[i - 1], and that will give you an IndexError.
To get the current last element of your mylist, you should use
mylist[-1] instead of mylist[i - 1]

Find/extract a sequence of integers within a list in python

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)

Give a list of nums... Add every 2 numbers (ex: 1,2,3,4 -> 3, 7)?

This is what I have so far... How do I get past having my countone go out of the list and crash the program? Or is there a cleaner way? Also, should I be using range or just having for i in list1? Also is there a way of setting i to have an initial value like in java? Edit: Forgot to mention that I'm practicing for interviews... Probably should avoid using built in functions... Or would this be acceptable?
list1 = [1,2,3,4,5,6,7,8,9,10]
list3 = []
countone = 0
for i in range(0, len(list1)-1):
firstnum = list1[i+countone]
secondnum = list1[i+countone+1]
print firstnum, "+", secondnum
sumnum = firstnum + secondnum
list3.append(sumnum)
countone += 1
print list3
You can use iter and zip:
list1 = [1,2,3,4,5,6,7,8,9,10]
it = iter(list1)
print([a + b for a,b in zip(it,it)])
[3, 7, 11, 15, 19]
iter creates an iterator, once you consume an element from an iterator t is gone and you get the next element:
In [4]: it = iter(list1)
In [5]: next(it)
Out[5]: 1
In [6]: next(it)
Out[6]: 2
In [7]: next(it)
Out[7]: 3
So zip(it,it) is basically calling next(it),next(it) until the iterator is exhausted leaving you with consecutive pairs of elements. It also avoids creating two new lists which will happen if you slice.
If you want a loop, use enumerate with a start index of 1 and append and reset a sm variable each time the ith index is evenly divisible by 2:
sm = 0
out = []
for i, ele in enumerate(list1, 1):
sm += ele
if i % 2 == 0:
out.append(sm)
sm = 0
print(out)
[3, 7, 11, 15, 19]
If you can use build-in functions you can do:
list(map(sum, zip(a[::2], a[1::2])))
Otherwise change your code to
list1 = [1,2,3,4,5,6,7,8,9,10]
list3 = []
for i in range(0, len(list1)-1, 2):
firstnum = list1[i]
secondnum = list1[i+1]
print(firstnum, "+", secondnum)
sumnum = firstnum + secondnum
list3.append(sumnum)
print(list3)
You don't need the variable counton.
You could use slicing to create 2 new lists and zip them together:
list3 = [a+b for a,b in zip(list1[::2], list1[1::2])]
Other answers are beautiful and using list comprehensions is a great idea, but I saw your comment, so I propose solution without using builtin functions.
I have slightly modified your code, so now it works fine.
for i in range(0,len(list1)-1,2):
firstnum = list1[i]
secondnum = list1[i+1]
print firstnum, "+", secondnum
sumnum = firstnum + secondnum
list3.append(sumnum)
You should also note that this code works only for lists with odd number of items. If the list is even, you should add the last element of list1 to list3.
from itertools import groupby
[sum(v) for _, v in groupby(list1, lambda x: (x+1) / 2)]

creating a reverse method for a python list from scratch

I want to create a reverse method for a list. I know there already is such a method built into python but I want to try it from scratch. Here's what I have and it seems to make sense to me but it just returns the list in the same order. My understanding was that lists are mutable and I could just reassign values in the loop.
def reverse(data_list):
length = len(data_list)
s = length
for item in data_list:
s = s - 1
data_list[s] = item
return data_list
def reverse(data_list):
return data_list[::-1]
>> reverse([1,2,3,4,5])
[5, 4, 3, 2, 1]
By the time you are half-way through the list, you have swapped all the items; as you continue through the second half, you are swapping them all back to their original locations again.
Instead try
def reverse(lst):
i = 0 # first item
j = len(lst)-1 # last item
while i<j:
lst[i],lst[j] = lst[j],lst[i]
i += 1
j -= 1
return lst
This can be used in two ways:
a = [1,2,3,4,5]
reverse(a) # in-place
print a # -> [5,4,3,2,1]
b = reverse(a[:]) # return the result of reversing a copy of a
print a # -> [5,4,3,2,1]
print b # -> [1,2,3,4,5]
You are changing the list that you iterate on it (data_list) because of that it's not working , try like this:
def reverse(data_list):
length = len(data_list)
s = length
new_list = [None]*length
for item in data_list:
s = s - 1
new_list[s] = item
return new_list
an easy way in python (without using the reverse function) is using the [] access operator with negative values such as (print and create a new list in reverse order):
x = [1, 2 ,3, 4, 5]
newx = []
for i in range(1, len(x)+1):
newx.append(x[-i])
print x[-i]
the function would be:
def reverse(list):
newlist = []
for i in range(1, len(list)+1):
newlist.append(list[-1])
return newlist
I do not get the same list when I try to run your code. But I also do not get a reversed list because the list is moving forward through the list state which is changing from end back. I think the way you are looking to do it is:
def reverse(data_set):
length = len(data_set)
for i in range(0, length / 2):
length = length - 1
hold = data_set[i]
data_set[i] = data_set[length]
data_set[length] = hold
return data_set
here we actually reverse in half the iterations and we memoize the value of the index we are changing so we can set the "reversal" in the same step.
word_reversed = ''
for i in range(len(word) -1, -1, -1):
word_reversed += word[i]
That will reverse a string of unknown length called (word) and call it (word_reversed).
I am using it to check to see if a word is a palindrome and I'm not allowed to use .reverse or word[::-1].
# Tyler G
# April 10, 2018
# Palindromes
import re
word = input("Palindromes are words that spell the same thing forwars or backwards, enter a word and see if its one!: ")
word = word.lower()
word = re.sub("[^a-zA-Z]+", "", word)
# count the number of characters in the string
# make a if <string>[0] = <string[counted char -1]
# repeat that over and over
# make a else print("not a ...")
word_reversed = ''
for i in range(len(word) - 1, -1, -1):
word_reversed += word[i]
itis = 0
if len(word) > 12:
print("It is not a Palindrome")
else:
for i in range(0, len(word)):
if word[i] == word_reversed[i]:
itis = itis + 1
else:
itis = itis - len(word)
if itis > 0:
print("It is a palindrome")
else:
print("It is NOT a Palindrome")
itis = 0
if len(word) > 12:
print("It is not a Palindrome")
There are two simple ways to solve the problem :
First using a temp variable :
maList = [2,5,67,8,99,34]
halfLen = len(maList) // 2
for index in range(halfLen):
temp = maList[index]
maList[index] = maList[len(maList) - 1 - index]
maList[len(maList) - 1 - index] = temp
print(maList)
Second is using a new list where to store the reversed values :
newList = []
for index,value in enumerate(maList):
newList.append(maList[len(maList) - 1 - index])
print(newList)
Something like this should work:
mylist = [1,2,3,4,5]
def reverse(orig_list):
data_list = orig_list[:]
length = len(data_list)
for i in xrange(0, length/2):
tmp = data_list[length-i-1]
data_list[length-i-1] = data_list[i]
data_list[i] = tmp
return data_list
reverse(mylist)
mylist
There are two ways of doing this
Pythonic Swap:
def Reverse_Function(item):
for i in range(len(item)/2):
item[i], item[-(i+1)] = item[-(i+1)], item[i]
return item
or
XOR application:
def Reverse_Function(item):
for i in range(len(item)/2):
item[i] = item[i] ^ item[-(i+1)]
item[-(i+1)] = item[i] ^ item[-(i+1)]
item[i] = item[i] ^ item[-(i+1)]
return item
Not looking to create a new list to hold your "temp" data?
Its simple if you look at the pattern:
reverse_list([a, b, c, d, e]) => [e, d, c, b, a]
This means that position 0 -> n, 1 -> (n - 1), 2 -> (n - 2). Which means that you can pop the last item and put it in the current index...
def reverse_list(list):
i = 0
while i < (len(list) - 1):
list.insert(i, list.pop())
i += 1
from array import *
x=array('i',[1,2,3,98,5,6,7,8])
y=array('i',[])
for i in x:
y.insert(0,i)
print(y)
Normally you can use either reversed() in general, or [::-1] on sequences. Since you are trying to implement a function from scratch, consider using stack, which is a common Abstract Data Type.
Given
import queue
s = "abc"
lst = list(s)
iter_ = iter(s)
Code
The following works on sequences and iterators similar to reversed():
def reversed_iter(iterable):
"""Yield items in reverse with a queue."""
stack = queue.LifoQueue() # 1
for x in iterable: # 2
stack.put(x)
while not stack.empty(): # 3
yield stack.get()
Demo
list(reversed_iter(s))
# ['c', 'b', 'a']
list(reversed_iter(lst))
# ['c', 'b', 'a']
list(reversed_iter(iter_))
# ['c', 'b', 'a']
Details
A stack is type of queue where the last element placed in is the first element removed. Imagine placing elements on top of each other in a container.
↓ ↑
| "c" |
| "b" |
| "a" |
-----------
Here the last element placed (enqueued) is the first to remove (dequeue), e.g. "c".
In the code, we:
Initialize a stack (the same as a LifoQueue)
Enqueue items to the stack
Dequeue items from the stack
The result are elements yielded in reversed order.
A queue is not required. Alternatively, we can emulate a stack with a simple list:
def reversed_iter(iterable):
"""Yield items in reverse with a list."""
stack = []
for x in iterable:
stack.append(x)
while stack:
yield stack.pop()
list(reversed_iter(s))
# ['c', 'b', 'a']
Emulating the Abstract Data Type is all that is needed in both examples.
list = [23, 3, 33, 44, 55, 16, 27 ];
1.more codes
def conver(list):
list.sort()
length = len(list)
s = length
new_list = [None]*length
for item in list:
s = s - 1
new_list[s] = item
print(new_list)
conver(list)
output:
[55, 44, 33, 27, 23, 16, 3]
2.easiest
list.sort()
list.reverse()
print(list)
output:
[55, 44, 33, 27, 23, 16, 3]
The following code demonstrates how to accept input:
a=[]
n=int(input("enter the no.of elements ")
for I in range(0,n):
a.insert(I,int(input(" enter elements: ")))
def rev_list(a):
print(a[::-1])
rev_list(a)
def reverseOrder():
my_list = []
a = input("What is your word?")
count = len(a) - 1
x = ''
for i in range(0, len(a)):
my_list.append(a[count])
count = count - 1
x = x.join(my_list)
print(x)
reverseOrder()
This is what I did. First I made an empty list. Then I stored users answer in a variable and subtracted one for indexing purposes. Now start a for loop and you set 'range' from 0 , len(a) then you append into the list backwards since count is = len(a). After that you set the .join function and join the list together. This is why there was variable x before the for loop.

Categories